Understand Web-App Anatomy
See a web app as a set of contracts among interface, server, data, identity, integrations, and evidence.
By the end
An architecture map and contract table for a real app, plus enough technical vocabulary to review Agent's implementation choices.
The interface is a client
The browser displays the user interface and collects interactions. It may validate obvious input and manage temporary state, but it is not a trustworthy authority for permissions or consequential rules. Anything running in a user's browser can be inspected or manipulated. Server-side code must revalidate identity, authorization, and inputs before changing protected state.
A component is a reusable interface responsibility: a form, table, card, navigation control, or state display. A route commonly maps a URL to a page or server handler. The names differ across frameworks; the durable question is who owns rendering, who owns validation, and who owns the side effect.
The server enforces rules
The server receives requests, validates them, checks access, applies business rules, reads or changes data, talks to external systems, and returns a response. A request has a method, destination, headers, and often a body. A response has a status, headers, and body. You do not need to memorize every status code to ask whether success and failure are explicit.
Business logic should express the workflow rather than live only inside button handlers. 'A reviewer may approve a submitted request, but not their own request' is a rule that should be testable independent of the visual component. Keeping the rule near server-side domain logic makes alternate interfaces and future automations safer.
The database preserves truth
A database stores records across requests and restarts. A table holds one kind of record, a row is one instance, and columns hold fields. A primary key identifies a record; a foreign key represents a relationship. A constraint prevents invalid data even when an interface or integration makes a mistake.
The current row is not always enough. Consequential workflows need history: who changed what, from which state to which state, when, and why. An append-only event or audit record can support debugging, trust, and recovery in ways that overwriting a status field cannot.
External systems are unreliable boundaries
An integration crosses a network and another organization's rules. Calls can be slow, duplicated, rejected, rate-limited, or successful even when your app times out waiting. Design explicit timeouts, retries only when safe, idempotency for repeated requests, and a local record of the attempt and result.
Do not make a screen wait indefinitely for work that can complete in the background. For long actions, create a job record, show pending state, process it, then show success or failure with evidence. If the product cannot support background processing yet, narrow the integration and disclose the limitation.
Observability connects the contracts
Logs record events; metrics aggregate behavior over time; traces connect one request across services; audit history explains business changes. Together they help answer what happened, where, to whom, and whether the system is healthy. Never log credentials or unnecessary personal data.
Use correlation identifiers to connect a user-visible receipt to server logs and an external call without exposing internals. A result page might show a safe request ID. An operator can then search logs and history for that ID. Evidence should be designed into the workflow instead of assembled only after an incident.
Working reference
Commands and patterns
Probe a local or Preview endpoint
curl -i https://YOUR-DEVELOPMENT-URL.example/health
An HTTP probe can reveal status, headers, and body separately from the visual interface. Use the actual safe development URL and an endpoint the project intentionally exposes.
Find likely boundary code
find . -type f \( -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.py' \) | head -120
Generate a bounded candidate list, then ask Agent which files own routes, validation, data access, and integrations instead of searching secret-bearing configuration.
When the happy path breaks
Failure modes
Symptom
Changing a hidden field or direct API request bypasses a permission shown in the UI.
Likely cause
Authorization exists only in browser code.
Recovery
Enforce identity, role, ownership, and allowed transition on the server for every protected operation.
Symptom
Retrying an external action creates duplicate tickets, charges, or messages.
Likely cause
The integration treats repeated delivery as a new action and has no idempotency or attempt record.
Recovery
Use a stable operation key, record attempts and external IDs, and retry only operations designed to be repeatable.
Symptom
A production failure cannot be connected to a user report.
Likely cause
The app has generic errors and unstructured logs with no safe correlation identifier.
Recovery
Return a safe request ID, log structured events around boundaries, and preserve business-state history.
Hands-on lab
Trace the six contracts
Map the planned approval action across interface, server, database, identity, external systems, and evidence before implementation.
- 01Describe the browser input, local validation, loading state, result, and recovery action.
- 02Define the server request, validation, authorization, domain rule, and response contract.
- 03Define records, keys, relationships, constraints, and an append-only history event.
- 04Name identity claims and permissions; explicitly test an unauthorized and self-approval attempt.
- 05If an integration exists, specify timeout, duplicate prevention, retry policy, attempt history, and user-visible status.
- 06Choose a correlation ID and the logs, metrics, and receipts that use it.
Deliverable: A six-column contract table detailed enough for Agent to implement and for a reviewer to test.
Reusable artifact
Web-app contract table
Use one row per user action or system event.
ACTION: [user or system action] INTERFACE: [input, local state, output, error recovery] SERVER: [request, validation, authorization, business rule, response] DATA: [read, write, constraint, transaction, history] IDENTITY: [actor, role, ownership, denied cases] INTEGRATION: [service, timeout, idempotency, retry, external ID] EVIDENCE: [safe request ID, logs, metric, audit event, visible receipt] TESTS: [happy, invalid, unauthorized, duplicate, dependency failure]
Before you move on
Receipt checklist
- The architecture map distinguishes browser, server, database, identity, integration, and observability responsibilities.
- A protected action is denied by server logic when the UI is bypassed.
- The data model preserves both current state and an attributable transition history.
- A user-visible request ID can be connected to safe logs or history without revealing a credential.
Primary sources
