Secure Architecture and Design Patterns
Keep transport handling, authentication, authorization, business rules, data access, and external integrations separated enough to review and test.
12.1 Security architecture principles
Secure by design and by default Minimize trusted computing base Explicit trust boundaries Separation of duties Fail closed for security decisions Compartmentalization and isolation Minimize sensitive data and retention Make important decisions auditable Prefer simple, reviewable mechanisms
12.2 Layered architecture
Keep transport handling, authentication, authorization, business rules, data access, and external integrations separated enough to review and test. Do not bury all security checks in the UI or assume a gateway can replace resource-level checks.
12.3 Policy enforcement points
Centralize shared policy logic where it improves consistency, but ensure every path is covered: HTTP handlers, background jobs, scheduled tasks, GraphQL resolvers, exports, internal APIs, and administrative tools. Test that bypass routes do not exist.
12.4 Secure state machines
For workflows such as enrollment, payment, password reset, and certificate issuance, define allowed transitions explicitly. Reject invalid or repeated transitions and perform state changes atomically.
Do not accept a client claim that an order is paid; verify the authoritative payment event and transition policy.
Text equivalent: an order starts in PENDING_PAYMENT; only a verified payment event moves it to PAID; from PAID it can be fulfilled or refunded; a pending order can be cancelled. Every other transition — for example FULFILLED back to PENDING_PAYMENT, or CANCELLED to PAID — is rejected.
Output (Node.js 24.18, TypeScript run with type stripping; tsc --strict reports no errors):
In a database, perform the transition as a conditional update (UPDATE orders SET state = 'PAID' WHERE id = ? AND state = 'PENDING_PAYMENT') and check that exactly one row changed — that makes the check and the write atomic.
PENDING_PAYMENT -> PAID -> FULFILLED
PENDING_PAYMENT -> CANCELLED
PAID -> REFUNDEDflowchart TD
P[PENDING_PAYMENT] -->|verified payment event| PAID[PAID]
PAID -->|fulfilment job| F[FULFILLED]
P -->|user or timeout| C[CANCELLED]
PAID -->|authorized refund| R[REFUNDED]type OrderState = "PENDING_PAYMENT" | "PAID" | "FULFILLED" | "CANCELLED" | "REFUNDED";
const ALLOWED: Record<OrderState, readonly OrderState[]> = {
PENDING_PAYMENT: ["PAID", "CANCELLED"],
PAID: ["FULFILLED", "REFUNDED"],
FULFILLED: [],
CANCELLED: [],
REFUNDED: [],
};
function transition(current: OrderState, next: OrderState): OrderState {
if (!ALLOWED[current].includes(next)) {
throw new Error(`transition ${current} -> ${next} is not allowed`);
}
return next;
}
let state: OrderState = "PENDING_PAYMENT";
for (const next of ["PAID", "FULFILLED", "PAID"] as OrderState[]) {
try {
state = transition(state, next);
console.log("now", state);
} catch (error) {
console.log("rejected:", (error as Error).message);
}
}now PAID
now FULFILLED
rejected: transition FULFILLED -> PAID is not allowed12.5 Zero Trust
Zero Trust is an architectural approach that avoids granting trust solely based on network location. Verify identity and context, use least privilege, continuously evaluate risk where appropriate, and assume that a component may be compromised. It is not a single product or a reason to add needless authentication prompts.
12.6 Secure multi-service design
Service identity and authorization Network segmentation and egress restrictions Message integrity and replay handling
Distributed tracing that excludes secrets Retry and timeout policies
Fail-safe behavior when identity or policy services are unavailable
Data consistency and duplicate event processing
12.7 Security design review
For each feature ask:
What is the asset?
Who can invoke it?
What are the trust boundaries?
What input is untrusted?
What permissions are required?
What can be abused at scale?
What data can leak through output, logs, caches, or errors?
How will the control be tested and monitored?
What happens during partial failure?
How can the feature be safely disabled or rolled back?
Quiz
? An API gateway checks the access token on every request. Do individual services still need authorization checks?
+ Yes — the gateway knows who is calling, not whether they may touch this particular object. :: Resource-level decisions belong close to the data.
- No — the gateway already authenticated the user. :: Authentication is not object authorization.
- Only for admin endpoints. :: Ordinary objects need checks too.
- Only if the services are on the internet. :: Internal paths and background jobs are also entry points.
? Which statement describes Zero Trust as used in the course?
- A product you install on the network perimeter :: It is an architectural approach, not a product.
+ Not granting trust based on network location alone; verify identity and context and use least privilege :: Correct.
- Requiring a password prompt on every click :: It is not a reason for needless prompts.
- Trusting nothing, so nothing is ever cached :: Unrelated.
? What should happen if the policy service is unavailable when a user requests a privileged action?
- Allow the action to keep the service available. :: That fails open for privileged operations.
+ Deny (fail closed) and surface a clear er
…