Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/engineering/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ mux.HandleFunc("GET /dashboard", ssr.RenderDashboard)
mux.HandleFunc("GET /api/patients", api.PatientsIndex)
```

The current code can plan route metadata for CLI reports and can emit SPA HTML files, CSS assets from compile-time processors and discovered page CSS inputs, stylesheet links, page-aware processor stylesheet selections, `gowdk-routes.json`, `gowdk-assets.json`, `gowdk-build-report.json`, the partial-update client runtime, and generated island runtime assets when needed for simple build-time pages with explicit or discovered component and layout files. It expands the first literal `paths {}` subset for dynamic SPA routes, binds those route params plus literal `build {}` data or imported Go build data into the current SPA `view {}` interpolation context, resolves typed component props/state contracts from Go module imports, runs state init functions at build time, and composes SPA page layouts through each layout's single `<slot />`; literal `build {}` string values can also interpolate current route params. It parses the supported action body subset and can generate SPA POST redirect handlers plus form input decoders, required-field validation wrappers, typed same-package action decoder glue, user action/API calls, CSRF token wiring by default for generated action and command POSTs, partial fragment responses, and concrete or dynamic standalone fragment routes through `addons/partial`; dynamic fragment params are attached to hook contexts through `runtime/app.Params(ctx)` and `runtime/app.TypedParams(ctx)`. `gowdk build --app` can also generate concrete and dynamic SSR routes for pages with request-time full-page behavior, with dynamic route matching, generated typed route-param bindings backed by `runtime/route`, and `load {}` execution for declared fields through `addons/ssr`; generated SSR load functions can return safe local redirects, generated SSR load failures can render optional `500.html`, and generated apps can render optional `404.html` for not-found responses. Generated guarded SSR, action, API, and fragment routes require `GOWDKGuardRegistry` for custom guard IDs and `GOWDKAuthProvider` for native `role:`/`permission:` RBAC guard IDs, fail Go compilation when required backing hooks are missing, and run declared guards through `runtime/guard` before user logic; ordinary guard errors fail closed while explicit guard helper errors can write no-store redirects or custom responses. Generated SSR, action, and API lanes also recover panics before response headers are written as no-store HTTP 500 responses without exposing panic values. `gowdk build --app` can generate an embedded Go app from that output, and `--bin` can compile it. `gowdk serve` can serve the generated SPA directory locally. It does not implement arbitrary client expressions yet. Only pages with `load {}` or `go ssr {}` should use request-time full-page rendering.
The current code can plan route metadata for CLI reports and can emit SPA HTML files, CSS assets from compile-time processors and discovered page CSS inputs, stylesheet links, page-aware processor stylesheet selections, `gowdk-routes.json`, `gowdk-assets.json`, `gowdk-build-report.json`, the partial-update client runtime, and generated island runtime assets when needed for simple build-time pages with explicit or discovered component and layout files. It expands the first literal `paths {}` subset for dynamic SPA routes, binds those route params plus literal `build {}` data or imported Go build data into the current SPA `view {}` interpolation context, resolves typed component props/state contracts from Go module imports, runs state init functions at build time, and composes SPA page layouts through each layout's single `<slot />`; literal `build {}` string values can also interpolate current route params. It parses the supported action body subset and can generate SPA POST redirect handlers plus form input decoders, required-field validation wrappers, typed same-package action decoder glue, user action/API calls, CSRF token wiring by default for generated action POSTs, command POSTs, and state-changing APIs, partial fragment responses, and concrete or dynamic standalone fragment routes through `addons/partial`; dynamic fragment params are attached to hook contexts through `runtime/app.Params(ctx)` and `runtime/app.TypedParams(ctx)`. `gowdk build --app` can also generate concrete and dynamic SSR routes for pages with request-time full-page behavior, with dynamic route matching, generated typed route-param bindings backed by `runtime/route`, and `load {}` execution for declared fields through `addons/ssr`; generated SSR load functions can return safe local redirects, generated SSR load failures can render optional `500.html`, and generated apps can render optional `404.html` for not-found responses. Generated guarded SSR, action, API, and fragment routes require `GOWDKGuardRegistry` for custom guard IDs and `GOWDKAuthProvider` for native `role:`/`permission:` RBAC guard IDs, fail Go compilation when required backing hooks are missing, and run declared guards through `runtime/guard` before user logic; ordinary guard errors fail closed while explicit guard helper errors can write no-store redirects or custom responses. Generated SSR, action, and API lanes also recover panics before response headers are written as no-store HTTP 500 responses without exposing panic values. `gowdk build --app` can generate an embedded Go app from that output, and `--bin` can compile it. `gowdk serve` can serve the generated SPA directory locally. It does not implement arbitrary client expressions yet. Only pages with `load {}` or `go ssr {}` should use request-time full-page rendering.

Guard metadata declarations are parsed and exposed in manifest/site-map output.
`runtime/guard` defines guard context, registry, ordered execution, no-store
Expand Down
5 changes: 3 additions & 2 deletions docs/engineering/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ readiness claim:
- Cap action/API request body size before form or JSON decoding; generated
apps default to 1 MiB and can override action/API caps with
`Build.BodyLimits`.
- Do not set `Build.CSRF.Disabled` for production generated action or command
handlers. Provide a stable `GOWDK_CSRF_SECRET` or configured
- Do not set `Build.CSRF.Disabled` for production generated action, command, or
state-changing API handlers unless another cross-site request strategy is in
place. Provide a stable `GOWDK_CSRF_SECRET` or configured
`Build.CSRF.SecretEnv` value in each runtime environment.
- Return explicit method-not-allowed responses for unsupported methods.
- Serve app assets with deterministic cache headers.
Expand Down
5 changes: 3 additions & 2 deletions docs/engineering/release-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,9 @@ Every 0.x minor release must have:
- [x] Replace outdated "planned but not complete" wording with precise
"first slice exists, not production enforcement" wording.
- [x] List implemented first slices: generated action decoding, unexpected
field rejection, direct literal request-shape validation, opt-in CSRF,
configurable action/API body caps, generated `http.Server` timeout defaults,
field rejection, direct literal request-shape validation, default generated
CSRF for state-changing endpoints, configurable action/API body caps,
generated `http.Server` timeout defaults,
`MaxHeaderBytes`, safe local redirect slice, guard execution slice, SSR panic
boundaries, and no-store request-time responses.
- [x] List incomplete production areas: auth/session policy, full guard
Expand Down
6 changes: 3 additions & 3 deletions docs/engineering/security-threat-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ current controls, and open follow-up areas for review.
| --- | --- | --- | --- |
| `.gwdk` source to compiler diagnostics | Parser, analyzer, `gowdk check`, LSP diagnostics | Stable diagnostic registry, source spans where available, redaction policy for secret-like values | Broader exact spans and diagnostic expansion remain tracked outside M5. |
| Generated logs and panic sinks | `runtime/app` panic boundaries, contract worker logs | Panic responses avoid stack traces; recovered panic logs pass through secret redaction | Broader app-owned logging guidance and redaction coverage remain planned. |
| Browser/client to action endpoints | POST forms, enhanced partial forms, command form adapters | Expected-field decoding, direct literal validation, configurable action body cap defaulting to 1 MiB, opt-in CSRF, 405 on wrong methods, no-store error responses | Broader upload policy, per-route limits, and full production CSRF rotation remain planned. |
| Browser/client to API endpoints | Generated API routes, contract query routes | Method dispatch, configurable API body cap defaulting to 1 MiB, rate-limit hook when addon is enabled | Public API hardening, typed helper expansion, and per-route policy are tracked in #24. |
| Browser/client to action endpoints | POST forms, enhanced partial forms, command form adapters | Expected-field decoding, direct literal validation, configurable action body cap defaulting to 1 MiB, default CSRF, 405 on wrong methods, no-store error responses | Broader upload policy, per-route limits, and full production CSRF rotation remain planned. |
| Browser/client to API endpoints | Generated API routes, contract query routes | Method dispatch, configurable API body cap defaulting to 1 MiB, generated CSRF for state-changing API methods, rate-limit hook when addon is enabled | Public API hardening, typed helper expansion, and per-route policy are tracked in #24. |
| Browser/client to fragments | Standalone fragments, action fragment responses | Fragment routing through generated handlers, escaped render core, no-store request-time responses; standalone fragments are GET-only and action fragments share the action cap | Broader auth/session policy remains planned. |
| Browser/client to SSR `load {}` | Request-time SSR routes, route-local error pages | SSR feature gate, guard execution, safe local redirect helpers, panic boundaries, no-store failures | Full guard contract, route-local auth/session policy, and richer request-time error policy remain planned. |
| Guard metadata to user authorization | `guard` declarations, `GOWDKGuardRegistry`, `GOWDKAuthProvider` | Guards run before generated request-time user logic; native RBAC helpers are defense-in-depth only | Backend resource authorization remains app-owned; full guard response contract is planned. |
Expand All @@ -49,7 +49,7 @@ current controls, and open follow-up areas for review.
| --- | --- | --- | --- |
| Submit unexpected action fields to overwrite handler input. | Integrity of action input. | Generated decoders reject unexpected fields and skip runtime fields such as CSRF. | Medium until broader typed helper contracts stabilize. |
| Send large request bodies to exhaust memory or handler time. | Availability of generated servers. | Generated action/API adapters cap bodies with configurable app-level limits; generated server entrypoints set HTTP timeouts and max-header defaults. | Medium because per-route limits remain planned. |
| Reuse or forge action CSRF tokens. | Cross-site action execution. | Generated CSRF is enabled by default for generated action/command POSTs and validates before decoding or user handlers run. | Medium while secret rotation and deployment guidance continue to harden. |
| Reuse or forge generated CSRF tokens. | Cross-site action, command, or state-changing API execution. | Generated CSRF is enabled by default for generated action POSTs, command POSTs, and state-changing APIs, and validates before decoding or user handlers run. | Medium while secret rotation and deployment guidance continue to harden. |
| Trigger handler panics and read stack traces or secret values. | Secret exposure and debugging data leakage. | Runtime panic boundaries avoid stack traces in responses and redact recovered-panic logs. | Medium because app-owned logs are outside generated control. |
| Use unsafe redirects to move users off-site. | Phishing or token leakage through redirects. | First slices require safe local redirects for generated action/SSR redirect paths. | Medium until full redirect allowlists and diagnostics are complete. |
| Embed local secrets into generated output. | Secret exposure in release artifacts. | Docs require generated output to avoid local env/private files. | High until exclusion tests cover `.env`, source maps, private files, and temp artifacts. |
Expand Down
20 changes: 11 additions & 9 deletions docs/engineering/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

The initial implementation is a compiler/runtime scaffold. Security-critical behavior appears incrementally in the actions, partial, API, embed, and SSR addons.

Do not treat current `act`, `api`, `partial`, `guard`, or SSR scaffolding as complete production enforcement. Current validation records and checks metadata; generated request decoding and opt-in CSRF enforcement exist, while authorization and broader request-time policy are still planned.
Do not treat current `act`, `api`, `partial`, `guard`, or SSR scaffolding as complete production enforcement. Current validation records and checks metadata; generated request decoding and default CSRF enforcement for browser-reachable state-changing endpoints exist, while authorization and broader request-time policy are still planned.

## Baseline Rules

Expand All @@ -18,9 +18,10 @@ Do not treat current `act`, `api`, `partial`, `guard`, or SSR scaffolding as com

## GOWDK-Specific Security Rules

- Generated actions and command endpoints enable CSRF by default. Production
configs must not set `Build.CSRF.Disabled`, and every runtime environment must
provide a stable CSRF secret.
- Generated actions, command endpoints, and state-changing API endpoints enable
CSRF by default. Production configs must not set `Build.CSRF.Disabled` unless
another cross-site request strategy is enforced, and every runtime environment
must provide a stable CSRF secret.
- Generated form decoders must validate expected fields and avoid mass assignment.
- Generated action forms must reject direct file inputs and multipart posts.
Uploads are user-owned API/server behavior with explicit size, storage,
Expand All @@ -38,8 +39,8 @@ Do not treat current `act`, `api`, `partial`, `guard`, or SSR scaffolding as com

Before generated app output is considered production-ready:

- Generated action and command CSRF must be enabled and configured with a
runtime secret.
- Generated action, command, and state-changing API CSRF must be enabled and
configured with a runtime secret.
- Redirects must reject unsafe external destinations unless explicitly allowed.
- Generated decoders must define how unknown, missing, repeated, and file fields are handled.
- Guards must have a documented execution contract, failure behavior, and test coverage.
Expand All @@ -57,9 +58,10 @@ posture from validated IR. `gowdk build` writes the posture as
`gowdk-security.json` in a non-served sibling report path under
`.gowdk/reports/<output-name>/`, and `gowdk audit --json` includes the same
posture inline. The built-in policy encodes the production-readiness gates
above — for example, actions and commands must enforce CSRF and APIs must not
be public by omission. Findings carry a stable diagnostic code, a `file:line`,
and remediation; run `gowdk explain <code>` for details.
above — for example, actions, commands, and state-changing APIs must enforce
CSRF, and APIs must not be public by omission. Findings carry a stable
diagnostic code, a `file:line`, and remediation; run `gowdk explain <code>` for
details.

`gowdk audit` is a standalone command. `gowdk build` never runs it, so it cannot
fail a build implicitly; run it on demand or in CI, where its non-zero exit on
Expand Down
11 changes: 6 additions & 5 deletions docs/language/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ func CreatePatient(ctx context.Context, request *http.Request) (response.Respons

`DecodeJSON[T]` decodes the capped request body into `T`, accepts
`application/json` and `+json` content types, rejects unknown object fields,
and rejects trailing JSON values. Empty `Content-Type` is accepted so simple
clients can still post JSON bodies.
rejects trailing JSON values, and rejects an empty or non-JSON `Content-Type`.

Query helpers read from `request.URL.Query()`:

Expand Down Expand Up @@ -138,9 +137,11 @@ rendering; build-time SPA HTML cannot enforce frontend page access.
- Missing or unsupported generated API bindings return HTTP 501 only in
development/default mode or when an explicit missing-backend migration flag is
set.
- Generated action CSRF wiring does not protect API endpoints. State-changing
APIs need normal Go auth/session checks and an explicit CSRF, same-site, or
token strategy appropriate to the API client.
- Generated state-changing API endpoints validate the generated CSRF token by
default. Browser clients must send the token in the configured CSRF header
such as `X-GOWDK-CSRF`; non-browser API designs can opt out with
`Build.CSRF.Disabled` only when they enforce another cross-site request
strategy.

Future API behavior must define:

Expand Down
Loading