rcf-lite 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +2 -0
- package/bin/view-supervisor-child.mjs +0 -0
- package/blueprints/application-api-rest/README.md +40 -0
- package/blueprints/application-api-rest/assets/middleware/auth-classes.md +45 -0
- package/blueprints/application-api-rest/assets/openapi/openapi-skeleton.yaml +322 -0
- package/blueprints/application-api-rest/assets/sample-data/sample-resources.json +53 -0
- package/blueprints/application-api-rest/assets/samples/request-response-pairs.md +204 -0
- package/blueprints/application-api-rest/blueprint.json +265 -0
- package/blueprints/application-api-rest/contributions/adrs/adr-301-application-api-rest-error-envelope.json +25 -0
- package/blueprints/application-api-rest/contributions/adrs/adr-302-application-api-rest-auth-model.json +25 -0
- package/blueprints/application-api-rest/contributions/adrs/adr-303-application-api-rest-api-versioning.json +25 -0
- package/blueprints/application-api-rest/contributions/adrs/adr-304-application-api-rest-logging.json +25 -0
- package/blueprints/application-api-rest/contributions/adrs/adr-305-application-api-rest-pagination.json +25 -0
- package/blueprints/application-api-rest/contributions/adrs/adr-306-application-api-rest-idempotency.json +25 -0
- package/blueprints/application-api-rest/contributions/adrs/adr-307-application-api-rest-openapi-generation.json +25 -0
- package/blueprints/application-api-rest/contributions/adrs/adr-308-application-api-rest-rate-limiting.json +25 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-001.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-002.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-003.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-004.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-005.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-006.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-007.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-008.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-009.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-010.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-011.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-012.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-013.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-014.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-015.json +18 -0
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-016.json +18 -0
- package/blueprints/application-api-rest/contributions/tacs/tac-301-application-api-rest-request-pipeline.json +48 -0
- package/blueprints/application-api-rest/contributions/tacs/tac-302-application-api-rest-auth-middleware.json +41 -0
- package/blueprints/application-api-rest/contributions/tacs/tac-303-application-api-rest-contract-surface.json +46 -0
- package/blueprints/application-api-rest/contributions/tacs/tac-304-application-api-rest-resource-layer.json +46 -0
- package/blueprints/application-api-rest/contributions/tacs/tac-305-application-api-rest-observability.json +40 -0
- package/blueprints/application-api-rest/contributions/tacs/tac-306-application-api-rest-operability.json +46 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2101.json +72 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2102.json +73 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2103.json +63 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2104.json +72 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2105.json +63 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2106.json +73 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2107.json +90 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2108.json +90 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2109.json +72 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2110.json +72 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2111.json +72 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2112.json +72 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2113.json +73 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2114.json +63 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2115.json +63 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2116.json +63 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2117.json +64 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2118.json +72 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2119.json +63 -0
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2120.json +73 -0
- package/blueprints/application-api-rest/docs/topics.md +46 -0
- package/blueprints/application-api-rest/guide/application-api-rest.md +41 -0
- package/blueprints/application-spa/README.md +90 -0
- package/blueprints/application-spa/assets/component-specs/actions-and-text-inputs.md +36 -0
- package/blueprints/application-spa/assets/component-specs/data-display.md +19 -0
- package/blueprints/application-spa/assets/component-specs/feedback-and-status.md +27 -0
- package/blueprints/application-spa/assets/component-specs/overlays.md +23 -0
- package/blueprints/application-spa/assets/component-specs/selection-controls.md +23 -0
- package/blueprints/application-spa/assets/sample-data/sample-entities.json +41 -0
- package/blueprints/application-spa/assets/tokens/design-tokens.json +140 -0
- package/blueprints/application-spa/assets/tokens/theme.css +169 -0
- package/blueprints/application-spa/assets/viewports.md +18 -0
- package/blueprints/application-spa/assets/wireframes/dashboard.md +48 -0
- package/blueprints/application-spa/assets/wireframes/detail.md +40 -0
- package/blueprints/application-spa/assets/wireframes/empty.md +31 -0
- package/blueprints/application-spa/assets/wireframes/error.md +46 -0
- package/blueprints/application-spa/assets/wireframes/form.md +50 -0
- package/blueprints/application-spa/assets/wireframes/list.md +45 -0
- package/blueprints/application-spa/assets/wireframes/session-expired.md +35 -0
- package/blueprints/application-spa/assets/wireframes/sign-in.md +41 -0
- package/blueprints/application-spa/assets/wireframes/sign-out.md +32 -0
- package/blueprints/application-spa/blueprint.json +387 -0
- package/blueprints/application-spa/contributions/adrs/adr-201-application-spa-routing.json +25 -0
- package/blueprints/application-spa/contributions/adrs/adr-202-application-spa-theming.json +25 -0
- package/blueprints/application-spa/contributions/adrs/adr-203-application-spa-client-state.json +25 -0
- package/blueprints/application-spa/contributions/adrs/adr-204-application-spa-error-envelope.json +25 -0
- package/blueprints/application-spa/contributions/adrs/adr-205-application-spa-auth-model.json +25 -0
- package/blueprints/application-spa/contributions/adrs/adr-206-application-spa-iconography.json +13 -0
- package/blueprints/application-spa/contributions/adrs/adr-207-application-spa-motion.json +13 -0
- package/blueprints/application-spa/contributions/adrs/adr-208-application-spa-i18n.json +13 -0
- package/blueprints/application-spa/contributions/adrs/adr-209-application-spa-telemetry-naming.json +13 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-001.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-002.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-003.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-004.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-005.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-006.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-007.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-008.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-009.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-010.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-011.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-012.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-013.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-014.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-015.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-016.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-017.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-018.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-019.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-020.json +18 -0
- package/blueprints/application-spa/contributions/requirements/application-spa-req-021.json +18 -0
- package/blueprints/application-spa/contributions/tacs/tac-201-application-spa-app-shell.json +45 -0
- package/blueprints/application-spa/contributions/tacs/tac-202-application-spa-theme-system.json +32 -0
- package/blueprints/application-spa/contributions/tacs/tac-203-application-spa-component-library.json +32 -0
- package/blueprints/application-spa/contributions/tacs/tac-204-application-spa-client-data-layer.json +27 -0
- package/blueprints/application-spa/contributions/tacs/tac-205-application-spa-forms-engine.json +27 -0
- package/blueprints/application-spa/contributions/tacs/tac-206-application-spa-telemetry.json +19 -0
- package/blueprints/application-spa/contributions/tacs/tac-207-application-spa-token-adherence-probe.json +57 -0
- package/blueprints/application-spa/contributions/tacs/tac-208-application-spa-icon-adherence-probe.json +56 -0
- package/blueprints/application-spa/contributions/tacs/tac-209-application-spa-csp-styled-adherence-probe.json +61 -0
- package/blueprints/application-spa/contributions/tacs/tac-210-application-spa-external-dependency-provisioning-probe.json +70 -0
- package/blueprints/application-spa/contributions/tacs/tac-211-application-spa-core-flow-e2e-probe.json +70 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1101.json +72 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1102.json +63 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1103.json +72 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1104.json +63 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1105.json +69 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1106.json +63 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1107.json +63 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1108.json +90 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1109.json +90 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1110.json +100 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1111.json +90 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1112.json +81 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1113.json +82 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1114.json +60 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1115.json +73 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1116.json +72 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1117.json +73 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1118.json +54 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1119.json +63 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1120.json +72 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1121.json +73 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1122.json +69 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1123.json +63 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1124.json +60 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1125.json +69 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1126.json +78 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1127.json +63 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1128.json +51 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1129.json +54 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1130.json +54 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1131.json +72 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1132.json +72 -0
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1133.json +72 -0
- package/blueprints/application-spa/docs/topics.md +57 -0
- package/blueprints/application-spa/guide/application-spa.md +40 -0
- package/blueprints/ci-pipeline/README.md +49 -0
- package/blueprints/ci-pipeline/assets/ci-provider-examples/github-actions.yml +61 -0
- package/blueprints/ci-pipeline/assets/ci-provider-examples/notes.md +50 -0
- package/blueprints/ci-pipeline/assets/report-samples/per-gate.json +12 -0
- package/blueprints/ci-pipeline/assets/report-samples/pipeline.json +28 -0
- package/blueprints/ci-pipeline/blueprint.json +46 -0
- package/blueprints/ci-pipeline/contributions/adrs/adr-701-ci-pipeline-ci-gates.json +25 -0
- package/blueprints/ci-pipeline/contributions/adrs/adr-702-ci-pipeline-strict-coverage-gate.json +25 -0
- package/blueprints/ci-pipeline/contributions/adrs/adr-703-ci-pipeline-node-only-runner.json +25 -0
- package/blueprints/ci-pipeline/contributions/adrs/adr-704-ci-pipeline-report-shape.json +25 -0
- package/blueprints/ci-pipeline/contributions/requirements/ci-pipeline-req-001.json +18 -0
- package/blueprints/ci-pipeline/contributions/requirements/ci-pipeline-req-002.json +18 -0
- package/blueprints/ci-pipeline/contributions/requirements/ci-pipeline-req-003.json +18 -0
- package/blueprints/ci-pipeline/contributions/requirements/ci-pipeline-req-004.json +18 -0
- package/blueprints/ci-pipeline/contributions/requirements/ci-pipeline-req-005.json +18 -0
- package/blueprints/ci-pipeline/contributions/requirements/ci-pipeline-req-006.json +18 -0
- package/blueprints/ci-pipeline/contributions/requirements/ci-pipeline-req-007.json +18 -0
- package/blueprints/ci-pipeline/contributions/requirements/ci-pipeline-req-008.json +18 -0
- package/blueprints/ci-pipeline/contributions/requirements/ci-pipeline-req-009.json +18 -0
- package/blueprints/ci-pipeline/contributions/requirements/ci-pipeline-req-010.json +18 -0
- package/blueprints/ci-pipeline/contributions/tacs/tac-701-ci-pipeline-gate-runner.json +59 -0
- package/blueprints/ci-pipeline/contributions/tacs/tac-702-ci-pipeline-gate-report.json +32 -0
- package/blueprints/ci-pipeline/contributions/tacs/tac-703-ci-pipeline-aggregate-report.json +41 -0
- package/blueprints/ci-pipeline/contributions/user-stories/ci-pipeline-us-6101.json +37 -0
- package/blueprints/ci-pipeline/contributions/user-stories/ci-pipeline-us-6102.json +36 -0
- package/blueprints/ci-pipeline/contributions/user-stories/ci-pipeline-us-6103.json +37 -0
- package/blueprints/ci-pipeline/contributions/user-stories/ci-pipeline-us-6104.json +37 -0
- package/blueprints/ci-pipeline/contributions/user-stories/ci-pipeline-us-6105.json +36 -0
- package/blueprints/ci-pipeline/contributions/user-stories/ci-pipeline-us-6106.json +36 -0
- package/blueprints/ci-pipeline/contributions/user-stories/ci-pipeline-us-6107.json +37 -0
- package/blueprints/ci-pipeline/contributions/user-stories/ci-pipeline-us-6108.json +37 -0
- package/blueprints/ci-pipeline/contributions/user-stories/ci-pipeline-us-6109.json +36 -0
- package/blueprints/ci-pipeline/contributions/user-stories/ci-pipeline-us-6110.json +36 -0
- package/blueprints/ci-pipeline/docs/topics.md +49 -0
- package/blueprints/ci-pipeline/guide/ci-pipeline.md +79 -0
- package/blueprints/deploy-cloudflare-workers/README.md +63 -0
- package/blueprints/deploy-cloudflare-workers/assets/ci-workflows/build-and-upload.yml.md +109 -0
- package/blueprints/deploy-cloudflare-workers/assets/ci-workflows/promote.yml.md +120 -0
- package/blueprints/deploy-cloudflare-workers/assets/verification/served-surface-probes.md +90 -0
- package/blueprints/deploy-cloudflare-workers/assets/wrangler-samples/bootstrap-vs-steady-state.md +87 -0
- package/blueprints/deploy-cloudflare-workers/assets/wrangler-samples/preview-alias-shape.md +86 -0
- package/blueprints/deploy-cloudflare-workers/assets/wrangler-samples/wrangler-toml-shape.md +85 -0
- package/blueprints/deploy-cloudflare-workers/blueprint.json +48 -0
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1301-deploy-cloudflare-workers-deployment-target.json +30 -0
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1302-deploy-cloudflare-workers-default-vendor.json +35 -0
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1303-deploy-cloudflare-workers-preview-vs-production.json +30 -0
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1304-deploy-cloudflare-workers-rollback-is-promote.json +25 -0
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1305-deploy-cloudflare-workers-dev-mode-drift.json +25 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-001.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-002.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-003.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-004.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-005.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-006.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-007.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-008.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-009.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-010.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-011.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-012.json +18 -0
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1301-deploy-cloudflare-workers-deploy-adapter.json +54 -0
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1302-deploy-cloudflare-workers-wrangler-manifest.json +45 -0
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1303-deploy-cloudflare-workers-preview-url-resolver.json +46 -0
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1304-deploy-cloudflare-workers-promote-gate.json +57 -0
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1305-deploy-cloudflare-workers-served-surface-verifier.json +51 -0
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1306-deploy-cloudflare-workers-deploy-ci-workflows.json +64 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12101.json +54 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12102.json +45 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12103.json +46 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12104.json +46 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12105.json +46 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12106.json +46 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12107.json +46 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12108.json +46 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12109.json +47 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12110.json +46 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12111.json +45 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12112.json +46 -0
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +46 -0
- package/blueprints/deploy-cloudflare-workers/guide/deploy-cloudflare-workers.md +74 -0
- package/blueprints/email-smtp-resend/README.md +45 -0
- package/blueprints/email-smtp-resend/assets/from-address-rotation-pattern.md +44 -0
- package/blueprints/email-smtp-resend/assets/resend-verification-pointer.md +25 -0
- package/blueprints/email-smtp-resend/assets/stub-adapter.md +65 -0
- package/blueprints/email-smtp-resend/blueprint.json +23 -0
- package/blueprints/email-smtp-resend/contributions/adrs/adr-401-email-smtp-resend-transport-choice.json +30 -0
- package/blueprints/email-smtp-resend/contributions/adrs/adr-402-email-smtp-resend-retry-and-backoff-posture.json +30 -0
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-001.json +18 -0
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-002.json +18 -0
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-003.json +18 -0
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-004.json +18 -0
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-005.json +18 -0
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-006.json +18 -0
- package/blueprints/email-smtp-resend/contributions/tacs/tac-401-email-smtp-resend-send-adapter.json +53 -0
- package/blueprints/email-smtp-resend/contributions/tacs/tac-402-email-smtp-resend-webhook-verifier.json +56 -0
- package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4101.json +45 -0
- package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4102.json +36 -0
- package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4103.json +45 -0
- package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4104.json +45 -0
- package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4105.json +36 -0
- package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4106.json +37 -0
- package/blueprints/email-smtp-resend/docs/topics.md +44 -0
- package/blueprints/email-smtp-resend/guide/email-smtp-resend.md +71 -0
- package/blueprints/observability-essentials/README.md +53 -0
- package/blueprints/observability-essentials/assets/probe-samples/liveness-body.json +4 -0
- package/blueprints/observability-essentials/assets/probe-samples/readiness-body.json +18 -0
- package/blueprints/observability-essentials/assets/status-page-samples/status-page-clean.html +22 -0
- package/blueprints/observability-essentials/assets/status-page-samples/status-page-with-notice.html +25 -0
- package/blueprints/observability-essentials/blueprint.json +54 -0
- package/blueprints/observability-essentials/contributions/adrs/adr-801-observability-essentials-health-probes.json +30 -0
- package/blueprints/observability-essentials/contributions/adrs/adr-802-observability-essentials-readiness-semantics.json +30 -0
- package/blueprints/observability-essentials/contributions/adrs/adr-803-observability-essentials-status-page-contract.json +30 -0
- package/blueprints/observability-essentials/contributions/adrs/adr-804-observability-essentials-probe-secrecy.json +25 -0
- package/blueprints/observability-essentials/contributions/adrs/adr-805-observability-essentials-notification-outcome-model.json +25 -0
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-001.json +18 -0
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-002.json +18 -0
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-003.json +18 -0
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-004.json +18 -0
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-005.json +18 -0
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-006.json +18 -0
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-007.json +18 -0
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-008.json +18 -0
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-009.json +18 -0
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-010.json +18 -0
- package/blueprints/observability-essentials/contributions/tacs/tac-801-observability-essentials-liveness-probe.json +32 -0
- package/blueprints/observability-essentials/contributions/tacs/tac-802-observability-essentials-readiness-probe.json +43 -0
- package/blueprints/observability-essentials/contributions/tacs/tac-803-observability-essentials-status-page.json +37 -0
- package/blueprints/observability-essentials/contributions/tacs/tac-804-observability-essentials-notification-outcome.json +42 -0
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7101.json +45 -0
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7102.json +45 -0
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7103.json +45 -0
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7104.json +45 -0
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7105.json +45 -0
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7106.json +45 -0
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7107.json +46 -0
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7108.json +47 -0
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7109.json +45 -0
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7110.json +46 -0
- package/blueprints/observability-essentials/docs/topics.md +57 -0
- package/blueprints/observability-essentials/guide/observability-essentials.md +68 -0
- package/blueprints/observability-probe-endpoints/README.md +53 -0
- package/blueprints/observability-probe-endpoints/assets/docker/dockerfile-healthcheck.md +19 -0
- package/blueprints/observability-probe-endpoints/assets/kubernetes/podspec-probes-separate-port.md +54 -0
- package/blueprints/observability-probe-endpoints/assets/kubernetes/podspec-probes.md +36 -0
- package/blueprints/observability-probe-endpoints/assets/load-balancer/health-check-config.md +23 -0
- package/blueprints/observability-probe-endpoints/assets/systemd/notify-service.md +30 -0
- package/blueprints/observability-probe-endpoints/assets/uptime-monitor/monitor-config.md +22 -0
- package/blueprints/observability-probe-endpoints/blueprint.json +44 -0
- package/blueprints/observability-probe-endpoints/contributions/adrs/adr-1501-observability-probe-endpoints-health-probes.json +30 -0
- package/blueprints/observability-probe-endpoints/contributions/adrs/adr-1502-observability-probe-endpoints-readiness-semantics.json +30 -0
- package/blueprints/observability-probe-endpoints/contributions/adrs/adr-1503-observability-probe-endpoints-kubernetes-default.json +30 -0
- package/blueprints/observability-probe-endpoints/contributions/adrs/adr-1504-observability-probe-endpoints-separate-port-option.json +30 -0
- package/blueprints/observability-probe-endpoints/contributions/adrs/adr-1505-observability-probe-endpoints-external-response-secrecy.json +30 -0
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-001.json +18 -0
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-002.json +18 -0
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-003.json +18 -0
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-004.json +18 -0
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-005.json +18 -0
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-006.json +18 -0
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-007.json +18 -0
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-008.json +18 -0
- package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1501-observability-probe-endpoints-profile-resolver.json +39 -0
- package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1502-observability-probe-endpoints-handler-set.json +40 -0
- package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1503-observability-probe-endpoints-listener-topology.json +51 -0
- package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1504-observability-probe-endpoints-non-http-adapters.json +39 -0
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14101.json +46 -0
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14102.json +46 -0
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14103.json +46 -0
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14104.json +45 -0
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14105.json +46 -0
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14106.json +45 -0
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14107.json +45 -0
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14108.json +46 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +51 -0
- package/blueprints/observability-probe-endpoints/guide/observability-probe-endpoints.md +83 -0
- package/blueprints/persistence-data-d1/README.md +50 -0
- package/blueprints/persistence-data-d1/assets/batch-usage/batch-atomicity-example.md +72 -0
- package/blueprints/persistence-data-d1/assets/facade-shape/facade-module-shape.md +115 -0
- package/blueprints/persistence-data-d1/assets/migration-shape/migration-file-shape.md +119 -0
- package/blueprints/persistence-data-d1/assets/wrangler-config/d1-binding-shape.md +93 -0
- package/blueprints/persistence-data-d1/blueprint.json +42 -0
- package/blueprints/persistence-data-d1/contributions/adrs/adr-1401-persistence-data-d1-store-model.json +30 -0
- package/blueprints/persistence-data-d1/contributions/adrs/adr-1402-persistence-data-d1-migration-discipline.json +30 -0
- package/blueprints/persistence-data-d1/contributions/adrs/adr-1403-persistence-data-d1-event-secrecy.json +25 -0
- package/blueprints/persistence-data-d1/contributions/adrs/adr-1404-persistence-data-d1-store-boundary.json +25 -0
- package/blueprints/persistence-data-d1/contributions/adrs/adr-1405-persistence-data-d1-recovery-model.json +30 -0
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-001.json +18 -0
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-002.json +18 -0
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-003.json +18 -0
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-004.json +18 -0
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-005.json +18 -0
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-006.json +18 -0
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-007.json +18 -0
- package/blueprints/persistence-data-d1/contributions/tacs/tac-1401-persistence-data-d1-facade.json +51 -0
- package/blueprints/persistence-data-d1/contributions/tacs/tac-1402-persistence-data-d1-migration-catalog.json +31 -0
- package/blueprints/persistence-data-d1/contributions/tacs/tac-1403-persistence-data-d1-deploy-gate.json +38 -0
- package/blueprints/persistence-data-d1/contributions/tacs/tac-1404-persistence-data-d1-recovery-runner.json +39 -0
- package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13101.json +45 -0
- package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13102.json +45 -0
- package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13103.json +46 -0
- package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13104.json +45 -0
- package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13105.json +45 -0
- package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13106.json +46 -0
- package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13107.json +38 -0
- package/blueprints/persistence-data-d1/docs/topics.md +59 -0
- package/blueprints/persistence-data-d1/guide/persistence-data-d1.md +77 -0
- package/blueprints/persistence-data-sqlite/README.md +50 -0
- package/blueprints/persistence-data-sqlite/assets/backup-procedures/hot-checkpoint-note.md +22 -0
- package/blueprints/persistence-data-sqlite/assets/backup-procedures/sqlite-file-copy.md +70 -0
- package/blueprints/persistence-data-sqlite/assets/schema-samples/catalog-file-layout.md +73 -0
- package/blueprints/persistence-data-sqlite/assets/schema-samples/migration-shape.md +76 -0
- package/blueprints/persistence-data-sqlite/blueprint.json +50 -0
- package/blueprints/persistence-data-sqlite/contributions/adrs/adr-601-persistence-data-sqlite-store-model.json +30 -0
- package/blueprints/persistence-data-sqlite/contributions/adrs/adr-602-persistence-data-sqlite-migration-discipline.json +30 -0
- package/blueprints/persistence-data-sqlite/contributions/adrs/adr-603-persistence-data-sqlite-event-secrecy.json +25 -0
- package/blueprints/persistence-data-sqlite/contributions/adrs/adr-604-persistence-data-sqlite-store-boundary.json +25 -0
- package/blueprints/persistence-data-sqlite/contributions/adrs/adr-605-persistence-data-sqlite-backup-model.json +25 -0
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-001.json +18 -0
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-002.json +18 -0
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-003.json +18 -0
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-004.json +18 -0
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-005.json +18 -0
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-006.json +18 -0
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-007.json +18 -0
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-008.json +18 -0
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-009.json +18 -0
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-010.json +18 -0
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-011.json +18 -0
- package/blueprints/persistence-data-sqlite/contributions/tacs/tac-601-persistence-data-sqlite-store.json +57 -0
- package/blueprints/persistence-data-sqlite/contributions/tacs/tac-602-persistence-data-sqlite-migration-runner.json +34 -0
- package/blueprints/persistence-data-sqlite/contributions/tacs/tac-603-persistence-data-sqlite-migration-catalog.json +31 -0
- package/blueprints/persistence-data-sqlite/contributions/tacs/tac-604-persistence-data-sqlite-backup-runner.json +33 -0
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5101.json +46 -0
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5102.json +46 -0
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5103.json +37 -0
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5104.json +45 -0
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5105.json +45 -0
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5106.json +46 -0
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5107.json +45 -0
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5108.json +46 -0
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5109.json +46 -0
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5110.json +37 -0
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5111.json +37 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +49 -0
- package/blueprints/persistence-data-sqlite/guide/persistence-data-sqlite.md +69 -0
- package/blueprints/security-auth-clerk/README.md +50 -0
- package/blueprints/security-auth-clerk/assets/authorisation/role-claim-mapping-sample.md +99 -0
- package/blueprints/security-auth-clerk/assets/middleware/node-middleware-shape.md +86 -0
- package/blueprints/security-auth-clerk/assets/wiring/clerk-provider-react.md +48 -0
- package/blueprints/security-auth-clerk/assets/wiring/clerk-provider-vue.md +41 -0
- package/blueprints/security-auth-clerk/blueprint.json +42 -0
- package/blueprints/security-auth-clerk/contributions/adrs/adr-1001-security-auth-clerk-auth-model.json +30 -0
- package/blueprints/security-auth-clerk/contributions/adrs/adr-1002-security-auth-clerk-middleware-boundary.json +25 -0
- package/blueprints/security-auth-clerk/contributions/adrs/adr-1003-security-auth-clerk-authorisation-adapter-contract.json +25 -0
- package/blueprints/security-auth-clerk/contributions/adrs/adr-1004-security-auth-clerk-claims-mapping-discipline.json +25 -0
- package/blueprints/security-auth-clerk/contributions/adrs/adr-1005-security-auth-clerk-session-lifecycle.json +25 -0
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-001.json +18 -0
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-002.json +18 -0
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-003.json +18 -0
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-004.json +18 -0
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-005.json +18 -0
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-006.json +18 -0
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-007.json +18 -0
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-008.json +18 -0
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-009.json +18 -0
- package/blueprints/security-auth-clerk/contributions/tacs/tac-1001-security-auth-clerk-middleware.json +42 -0
- package/blueprints/security-auth-clerk/contributions/tacs/tac-1002-security-auth-clerk-authorisation-adapter.json +30 -0
- package/blueprints/security-auth-clerk/contributions/tacs/tac-1003-security-auth-clerk-session-verifier.json +38 -0
- package/blueprints/security-auth-clerk/contributions/tacs/tac-1004-security-auth-clerk-claims-mapper.json +22 -0
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9101.json +46 -0
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9102.json +38 -0
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9103.json +46 -0
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9104.json +46 -0
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9105.json +36 -0
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9106.json +36 -0
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9107.json +37 -0
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9108.json +36 -0
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9109.json +36 -0
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9110.json +37 -0
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9111.json +36 -0
- package/blueprints/security-auth-clerk/docs/topics.md +56 -0
- package/blueprints/security-auth-clerk/guide/security-auth-clerk.md +71 -0
- package/blueprints/security-auth-keycloak/README.md +56 -0
- package/blueprints/security-auth-keycloak/assets/local-container/keycloak-bootstrap.md +54 -0
- package/blueprints/security-auth-keycloak/assets/middleware/verifier-wiring.md +93 -0
- package/blueprints/security-auth-keycloak/assets/mock-introspection/mock-introspection-shape.md +62 -0
- package/blueprints/security-auth-keycloak/assets/provider-router/router-shape.md +71 -0
- package/blueprints/security-auth-keycloak/assets/realm-skeleton/realm-config-shape.md +55 -0
- package/blueprints/security-auth-keycloak/blueprint.json +49 -0
- package/blueprints/security-auth-keycloak/contributions/adrs/adr-1201-security-auth-keycloak-auth-model.json +35 -0
- package/blueprints/security-auth-keycloak/contributions/adrs/adr-1202-security-auth-keycloak-verification-mode-choice.json +30 -0
- package/blueprints/security-auth-keycloak/contributions/adrs/adr-1203-security-auth-keycloak-provider-routing-seam.json +30 -0
- package/blueprints/security-auth-keycloak/contributions/adrs/adr-1204-security-auth-keycloak-session-vs-token-contract.json +25 -0
- package/blueprints/security-auth-keycloak/contributions/adrs/adr-1205-security-auth-keycloak-jwks-rotation-cache-lifetime.json +30 -0
- package/blueprints/security-auth-keycloak/contributions/adrs/adr-1206-security-auth-keycloak-refresh-and-sign-out-posture.json +25 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-001.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-002.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-003.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-004.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-005.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-006.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-007.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-008.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-009.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-010.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-011.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-012.json +18 -0
- package/blueprints/security-auth-keycloak/contributions/tacs/tac-1201-security-auth-keycloak-discovery-client.json +51 -0
- package/blueprints/security-auth-keycloak/contributions/tacs/tac-1202-security-auth-keycloak-jwt-verifier.json +46 -0
- package/blueprints/security-auth-keycloak/contributions/tacs/tac-1203-security-auth-keycloak-introspection-client.json +45 -0
- package/blueprints/security-auth-keycloak/contributions/tacs/tac-1204-security-auth-keycloak-provider-router.json +37 -0
- package/blueprints/security-auth-keycloak/contributions/tacs/tac-1205-security-auth-keycloak-role-adapter.json +32 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11101.json +47 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11102.json +45 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11103.json +36 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11104.json +36 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11105.json +45 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11106.json +46 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11107.json +45 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11108.json +45 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11109.json +37 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11110.json +45 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11111.json +45 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11112.json +37 -0
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11113.json +36 -0
- package/blueprints/security-auth-keycloak/docs/topics.md +74 -0
- package/blueprints/security-auth-keycloak/guide/security-auth-keycloak.md +81 -0
- package/blueprints/security-auth-magic-link/README.md +46 -0
- package/blueprints/security-auth-magic-link/assets/email-templates/magic-link-email.md +44 -0
- package/blueprints/security-auth-magic-link/assets/email-templates/stub-adapter.md +55 -0
- package/blueprints/security-auth-magic-link/assets/principal-registry-samples/allow-list-file.md +46 -0
- package/blueprints/security-auth-magic-link/assets/principal-registry-samples/single-address.md +35 -0
- package/blueprints/security-auth-magic-link/blueprint.json +45 -0
- package/blueprints/security-auth-magic-link/contributions/adrs/adr-501-security-auth-magic-link-model.json +30 -0
- package/blueprints/security-auth-magic-link/contributions/adrs/adr-502-security-auth-magic-link-token-secrecy.json +25 -0
- package/blueprints/security-auth-magic-link/contributions/adrs/adr-503-security-auth-magic-link-anti-enumeration-budget.json +25 -0
- package/blueprints/security-auth-magic-link/contributions/adrs/adr-504-security-auth-magic-link-session-lifecycle.json +30 -0
- package/blueprints/security-auth-magic-link/contributions/adrs/adr-505-security-auth-magic-link-rate-limiting.json +25 -0
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-001.json +18 -0
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-002.json +18 -0
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-003.json +18 -0
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-004.json +18 -0
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-005.json +18 -0
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-006.json +18 -0
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-007.json +18 -0
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-008.json +18 -0
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-009.json +18 -0
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-010.json +18 -0
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-011.json +18 -0
- package/blueprints/security-auth-magic-link/contributions/tacs/tac-501-security-auth-magic-link-manager.json +45 -0
- package/blueprints/security-auth-magic-link/contributions/tacs/tac-502-security-auth-magic-link-session-manager.json +46 -0
- package/blueprints/security-auth-magic-link/contributions/tacs/tac-503-security-auth-magic-link-login-routes.json +76 -0
- package/blueprints/security-auth-magic-link/contributions/tacs/tac-504-security-auth-magic-link-email-delivery-adapter.json +26 -0
- package/blueprints/security-auth-magic-link/contributions/tacs/tac-505-security-auth-magic-link-principal-registry.json +26 -0
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3101.json +64 -0
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3102.json +54 -0
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3103.json +45 -0
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3104.json +55 -0
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3105.json +46 -0
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3106.json +46 -0
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3107.json +54 -0
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3108.json +46 -0
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3109.json +48 -0
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3110.json +45 -0
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3111.json +45 -0
- package/blueprints/security-auth-magic-link/docs/topics.md +45 -0
- package/blueprints/security-auth-magic-link/guide/security-auth-magic-link.md +65 -0
- package/blueprints/security-auth-oauth2/README.md +50 -0
- package/blueprints/security-auth-oauth2/assets/mock-provider/mock-oidc-shape.md +55 -0
- package/blueprints/security-auth-oauth2/assets/provider-selector/list-shape.md +27 -0
- package/blueprints/security-auth-oauth2/assets/providers/generic-oidc-discovery.md +31 -0
- package/blueprints/security-auth-oauth2/assets/providers/github-oauth2-only.md +31 -0
- package/blueprints/security-auth-oauth2/assets/providers/google-oidc.md +31 -0
- package/blueprints/security-auth-oauth2/assets/session-bridge/opaque-handle-shape.md +59 -0
- package/blueprints/security-auth-oauth2/blueprint.json +44 -0
- package/blueprints/security-auth-oauth2/contributions/adrs/adr-1101-security-auth-oauth2-auth-model.json +35 -0
- package/blueprints/security-auth-oauth2/contributions/adrs/adr-1102-security-auth-oauth2-provider-abstraction-contract.json +25 -0
- package/blueprints/security-auth-oauth2/contributions/adrs/adr-1103-security-auth-oauth2-pkce-discipline.json +25 -0
- package/blueprints/security-auth-oauth2/contributions/adrs/adr-1104-security-auth-oauth2-session-bridge-shape.json +25 -0
- package/blueprints/security-auth-oauth2/contributions/adrs/adr-1105-security-auth-oauth2-refresh-token-posture.json +25 -0
- package/blueprints/security-auth-oauth2/contributions/adrs/adr-1106-security-auth-oauth2-multi-provider-routing.json +25 -0
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-001.json +18 -0
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-002.json +18 -0
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-003.json +18 -0
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-004.json +18 -0
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-005.json +18 -0
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-006.json +18 -0
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-007.json +18 -0
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-008.json +18 -0
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-009.json +18 -0
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-010.json +18 -0
- package/blueprints/security-auth-oauth2/contributions/tacs/tac-1101-security-auth-oauth2-flow-controller.json +61 -0
- package/blueprints/security-auth-oauth2/contributions/tacs/tac-1102-security-auth-oauth2-provider-adapter.json +33 -0
- package/blueprints/security-auth-oauth2/contributions/tacs/tac-1103-security-auth-oauth2-session-bridge.json +51 -0
- package/blueprints/security-auth-oauth2/contributions/tacs/tac-1104-security-auth-oauth2-provider-selector.json +29 -0
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10101.json +47 -0
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10102.json +45 -0
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10103.json +36 -0
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10104.json +36 -0
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10105.json +55 -0
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10106.json +45 -0
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10107.json +46 -0
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10108.json +46 -0
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10109.json +37 -0
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10110.json +37 -0
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10111.json +28 -0
- package/blueprints/security-auth-oauth2/docs/topics.md +58 -0
- package/blueprints/security-auth-oauth2/guide/security-auth-oauth2.md +65 -0
- package/blueprints/security-secrets-management/README.md +48 -0
- package/blueprints/security-secrets-management/assets/cli-usage/agent-access-pattern.md +69 -0
- package/blueprints/security-secrets-management/assets/manifest-samples/environment-aware-example.md +33 -0
- package/blueprints/security-secrets-management/assets/manifest-samples/secrets-yaml-shape.md +74 -0
- package/blueprints/security-secrets-management/assets/ui-integration/three-way-choice.md +44 -0
- package/blueprints/security-secrets-management/blueprint.json +43 -0
- package/blueprints/security-secrets-management/contributions/adrs/adr-901-security-secrets-management-secrets-source.json +30 -0
- package/blueprints/security-secrets-management/contributions/adrs/adr-902-security-secrets-management-default-vendor.json +35 -0
- package/blueprints/security-secrets-management/contributions/adrs/adr-903-security-secrets-management-agent-access-discipline.json +25 -0
- package/blueprints/security-secrets-management/contributions/adrs/adr-904-security-secrets-management-dotenv-reflection.json +25 -0
- package/blueprints/security-secrets-management/contributions/adrs/adr-905-security-secrets-management-rotation-and-audit.json +30 -0
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-001.json +18 -0
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-002.json +18 -0
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-003.json +18 -0
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-004.json +18 -0
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-005.json +18 -0
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-006.json +18 -0
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-007.json +18 -0
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-008.json +18 -0
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-009.json +18 -0
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-010.json +18 -0
- package/blueprints/security-secrets-management/contributions/tacs/tac-901-security-secrets-management-manager-client.json +52 -0
- package/blueprints/security-secrets-management/contributions/tacs/tac-902-security-secrets-management-manifest.json +34 -0
- package/blueprints/security-secrets-management/contributions/tacs/tac-903-security-secrets-management-env-reflector.json +46 -0
- package/blueprints/security-secrets-management/contributions/tacs/tac-904-security-secrets-management-rotation-gate.json +57 -0
- package/blueprints/security-secrets-management/contributions/tacs/tac-905-security-secrets-management-agent-cli.json +59 -0
- package/blueprints/security-secrets-management/contributions/user-stories/security-secrets-management-us-8101.json +46 -0
- package/blueprints/security-secrets-management/contributions/user-stories/security-secrets-management-us-8102.json +45 -0
- package/blueprints/security-secrets-management/contributions/user-stories/security-secrets-management-us-8103.json +37 -0
- package/blueprints/security-secrets-management/contributions/user-stories/security-secrets-management-us-8104.json +45 -0
- package/blueprints/security-secrets-management/contributions/user-stories/security-secrets-management-us-8105.json +55 -0
- package/blueprints/security-secrets-management/contributions/user-stories/security-secrets-management-us-8106.json +46 -0
- package/blueprints/security-secrets-management/contributions/user-stories/security-secrets-management-us-8107.json +46 -0
- package/blueprints/security-secrets-management/contributions/user-stories/security-secrets-management-us-8108.json +45 -0
- package/blueprints/security-secrets-management/contributions/user-stories/security-secrets-management-us-8109.json +46 -0
- package/blueprints/security-secrets-management/contributions/user-stories/security-secrets-management-us-8110.json +45 -0
- package/blueprints/security-secrets-management/docs/topics.md +46 -0
- package/blueprints/security-secrets-management/guide/security-secrets-management.md +68 -0
- package/fixtures/canary-manifest.json +1 -101
- package/package.json +16 -10
- package/rcf/.identity/profile.md +37 -0
- package/rcf/knowledge/INDEX.md +12 -0
- package/rcf/knowledge/README.md +41 -0
- package/rcf/knowledge/docs/.gitkeep +0 -0
- package/rcf/knowledge/notes/.gitkeep +0 -0
- package/scripts/preinstall-node-check.mjs +61 -0
- package/src/blueprint/apply.js +12 -6
- package/src/blueprint/conflicts.js +8 -8
- package/src/blueprint/index.js +2 -1
- package/src/blueprint/list.js +60 -0
- package/src/blueprint/loader.js +26 -1
- package/src/blueprint/namespace.js +20 -16
- package/src/blueprint/shelf-resolver.js +173 -0
- package/src/blueprint/supersede.js +3 -2
- package/src/browser-verify/invariants.js +40 -0
- package/src/browser-verify/runner.js +2 -0
- package/src/cli/blueprint.js +53 -9
- package/src/cli/init.js +2 -0
- package/src/core/store/validator.js +15 -27
- package/src/core/store/writer.js +64 -2
- package/src/ruleset/ruleset.json +1 -1
- package/src/setup/agent-setup.js +28 -10
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# security-auth-keycloak blueprint coordination vocabulary
|
|
2
|
+
|
|
3
|
+
This file is the security-auth-keycloak half of the cross-blueprint contract. The Phase 1 conflict detector matches scope:global ADR topics by EXACT string equality, and AC ids are unnamespaced by the 0.4.4 grammar. Any blueprint intended to compose with this one must reuse these exact strings and respect these bands.
|
|
4
|
+
|
|
5
|
+
## Global ADR topics this blueprint contributes (exact strings)
|
|
6
|
+
|
|
7
|
+
| Topic string | security-auth-keycloak contribution | Composition intent |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `authModel` | ADR-1201-security-auth-keycloak-auth-model | Deliberate conflict on the same string minted by `security-auth-magic-link` (ADR-501), `security-auth-clerk` (ADR-1001), `security-auth-oauth2` (ADR-1101), the client half of `application-spa` (ADR-205), and the server half of `application-api-rest` (ADR-302). This blueprint's shape is delegated identity to a Keycloak realm the operator runs, federated through OIDC authorisation-code + PKCE, with per-realm verification mode (JWKS or introspection). A composing blueprint that holds a different opinion on the authentication model contributes its own scope:global ADR on this exact string and lets composition surface the pairing. Expected resolution: one project-level ADR that fixes the project's authentication model for both the client tier and the server tier, with a resolution recorded on `manifest.resolutions[]` or via `--resolve authModel=project:<ADR-id>` on the add |
|
|
10
|
+
|
|
11
|
+
The security-auth-keycloak blueprint claims one global topic. Every other contribution is scope-local (ADR-1202 through ADR-1206 name the verification-mode choice, the provider-routing seam, the session-vs-token contract, the JWKS rotation-cache lifetime, and the refresh-and-sign-out posture without contributing global topics; a composing blueprint that holds a different opinion on any of them authors its own project-level ADR if it wants to override).
|
|
12
|
+
|
|
13
|
+
Rules for new topics (inherited from the application-spa, application-api-rest, security-auth-magic-link, security-auth-clerk, security-auth-oauth2, persistence-data-sqlite, ci-pipeline, observability-essentials, and security-secrets-management vocabularies, restated as law): lower camelCase, one concept per topic, no version suffixes. A topic names the decision area, not the chosen answer. Do not mint variants of existing strings (`auth`, `authentication`, `identityProvider`, `keycloakProvider` are all wrong when `authModel` already exists).
|
|
14
|
+
|
|
15
|
+
## The deliberate authModel conflict, restated
|
|
16
|
+
|
|
17
|
+
This blueprint is the vendor-committed Keycloak shape of the `authModel` decision. Three other shipped auth-family blueprints hold different shapes on the same topic:
|
|
18
|
+
|
|
19
|
+
- `security-auth-magic-link` (ADR-501): passwordless magic-link with server-issued opaque cookie sessions. Local-first, no third-party identity dependency.
|
|
20
|
+
- `security-auth-clerk` (ADR-1001): hosted identity via Clerk; the vendor owns the sign-in surface, credential storage, MFA, and account recovery; the project owns a middleware boundary against Clerk's session-verification.
|
|
21
|
+
- `security-auth-oauth2` (ADR-1101): delegated identity via OAuth2 authorisation-code + PKCE against any project-configured IdP. Vendor-neutral; the project drops in the provider it wants.
|
|
22
|
+
- `security-auth-keycloak` (ADR-1201, this blueprint): delegated identity to a Keycloak realm the operator runs, federated through OIDC. Vendor-committed; larger ops footprint; full self-hosted control.
|
|
23
|
+
|
|
24
|
+
Composing any two of these on one project raises a `globalAdrTopic` conflict on `authModel` at `rcf define blueprint add`. The four documented resolutions apply: adopt the incoming, keep the existing, author a project-level supersede ADR, or `--resolve authModel=project:<ADR-id>` on the add. The composition-precedent (SPA + REST on `errorEnvelope` and `authModel`) is the same pattern the client half and the server half of the wire contract have already established; the auth-family blueprints follow it.
|
|
25
|
+
|
|
26
|
+
## Id number bands (registry bootstrap)
|
|
27
|
+
|
|
28
|
+
AC ids (and therefore US numeric ids, which anchor them) are NOT namespaced by the 0.4.4 schema grammar; the band allocation IS the AC-collision enforcement mechanism. Composing blueprints take a fresh band rather than proposing namespaced AC ids. Band allocation is ratified policy (2026-08-19, extended by round-2 outcomes 2026-08-30 for the four-digit ADR/TAC suffix widening); this table is the shared registry-bootstrap replicated across every shipped and forthcoming blueprint's `docs/topics.md` until a mechanism-side central registry lands (v1.1 candidate).
|
|
29
|
+
|
|
30
|
+
This table is maintained shelf-wide across every blueprint's `docs/topics.md`. Rows are recorded at ship, never predicted.
|
|
31
|
+
|
|
32
|
+
| Blueprint | US band | ADR/TAC suffix block | Status | Global topics |
|
|
33
|
+
|---|---|---|---|---|
|
|
34
|
+
| application-spa | 1101-1899 | 2xx | shipped v1.3.0 | `clientRouting`, `theming`, `clientState`, `errorEnvelope`, `authModel` |
|
|
35
|
+
| application-api-rest | 2101-2899 | 3xx | shipped v1.0.0 | `errorEnvelope`, `authModel`, `apiVersioning`, `logging` |
|
|
36
|
+
| security-auth-magic-link | 3101-3899 | 5xx | shipped v1.0.0 | `authModel` |
|
|
37
|
+
| email-smtp-resend | 4101-4899 | 4xx | shipped v1.0.0 | none |
|
|
38
|
+
| hello-panel (walkthrough exemplar) | 4101-4899 | 4xx | doc-reserved; teaching exemplar in `packages/rcf-lite/docs/blueprint-authoring-walkthrough.md`, not shipped as a blueprint directory | `operatorPanel` |
|
|
39
|
+
| persistence-data-sqlite | 5101-5899 | 6xx | shipped v1.0.0 | `persistenceStore`, `migrationDiscipline` |
|
|
40
|
+
| ci-pipeline | 6101-6899 | 7xx | shipped v1.0.0 | `ciGates`, `strictCoverageGate` |
|
|
41
|
+
| observability-essentials | 7101-7899 | 8xx | shipped v1.0.0 | `healthProbes`, `readinessSemantics`, `statusPageContract` |
|
|
42
|
+
| security-secrets-management | 8101-8899 | 9xx | shipped v1.0.0 | `secretsSource` |
|
|
43
|
+
| security-auth-clerk | 9101-9899 | 10xx | shipped v1.0.0 | `authModel` |
|
|
44
|
+
| security-auth-oauth2 | 10101-10899 | 11xx | shipped v1.0.0 | `authModel` |
|
|
45
|
+
| security-auth-keycloak | 11101-11899 | 12xx | shipped v1.0.0 | `authModel` |
|
|
46
|
+
| deploy-cloudflare-workers | 12101-12899 | 13xx | shipped v1.0.0 | `deploymentTarget` |
|
|
47
|
+
| persistence-data-d1 | 13101-13899 | 14xx | shipped v1.0.0 | `persistenceStore`, `migrationDiscipline` |
|
|
48
|
+
| observability-probe-endpoints | 14101-14899 | 15xx | shipped v1.0.0 | `healthProbes`, `readinessSemantics` |
|
|
49
|
+
|
|
50
|
+
US 11101-11113 sit at the LOW end of the 11101-11899 band on purpose. A project-side story that mechanically derives from a security-auth-keycloak REQ id into the number `11113` would collide against security-auth-keycloak-US-11113 in this package; the band leaves headroom at the HIGH end (US 11181-11899) so a project's own stories anchored to security-auth-keycloak REQs can allocate without conflict. The watchpost run4 lesson applies here too.
|
|
51
|
+
|
|
52
|
+
The ADR/TAC suffix block 1201-1299 is the third block in the four-digit suffix space; `security-auth-clerk` opened the door at 1001-1099 and `security-auth-oauth2` took 1101-1199. Every shipped blueprint continues to load, validate, and audit against this shape without a schema change: rcf-schemas 0.5.0 `adrId` and `tacId` patterns are `^ADR-\d{3,}(-[a-z0-9]+...)?$` (three-digit minimum, unbounded above); four-digit and higher suffixes validate verbatim. The registry table above records the growth for a downstream author reaching for the next block.
|
|
53
|
+
|
|
54
|
+
## Provider-aware install-design shape (plain language, no named second issuer)
|
|
55
|
+
|
|
56
|
+
The blueprint is Keycloak-committed. What the install design is AWARE of is that a project may deploy this mechanism in an environment where a receiving system's request stream also carries tokens issued by another OAuth2 or OIDC server. This shape is NOT a claim about the blueprint's mechanism reach - the blueprint verifies against Keycloak realms only, and refuses to name any specific second issuer. The shape lives at the seam where a project's OWN middleware decides which issuer is authoritative for a request:
|
|
57
|
+
|
|
58
|
+
- TAC-1204 (the provider router) contributes the pure-function contract `route(request) -> { realmSlug, verificationMode } | 'notThisIssuer'`. A project with only Keycloak wires it to a constant; a project with two Keycloak realms wires it to inspect a project-chosen request feature; a project with Keycloak alongside a non-Keycloak issuer returns the sentinel and the project's own middleware chain above owns what happens next.
|
|
59
|
+
- REQ-004 (the introspection path) speaks the RFC 7662 shape whether the issuer is Keycloak or another conforming server. The blueprint reaches only for the endpoint declared on the realm's discovery; a project that has chosen to consult a non-Keycloak issuer at introspection is a project-level ADR conversation, not a mechanism change here.
|
|
60
|
+
|
|
61
|
+
The blueprint refuses to encode:
|
|
62
|
+
|
|
63
|
+
- A specific second issuer's name, product, or integration.
|
|
64
|
+
- A specific request marker (a header name, a path prefix, a claim, a subdomain shape) the routing function would inspect.
|
|
65
|
+
- A specific dual-issuer deployment shape (a docker-compose recipe, a Kubernetes topology, a load-balancer rule).
|
|
66
|
+
- A specific standards-suite reference the ratified reshape ruling excluded from this blueprint.
|
|
67
|
+
|
|
68
|
+
A project that has one Keycloak realm inherits the seam at zero cost (constant routeFn). A project that has two Keycloak realms pays one function call per request. A project with an issuer above this blueprint's reach pays one function call per request and owns the routing policy on its own ADR.
|
|
69
|
+
|
|
70
|
+
## Shared expectations for future composing blueprints
|
|
71
|
+
|
|
72
|
+
- Reuse `authModel` exactly as spelled here when your blueprint holds an opinion on the project's authentication model; contribute your own scope:global ADR on that string and let composition surface the pairing.
|
|
73
|
+
- Verification-mode choice (ADR-1202), provider-routing seam (ADR-1203), session-vs-token contract (ADR-1204), JWKS rotation-cache lifetime (ADR-1205), and refresh-and-sign-out posture (ADR-1206) are scope-local. A composing blueprint that holds an opinion on any of them authors its own project-level ADR; none of them are minted as globals because the space of legitimate variations is smaller than the space of legitimate authentication-model variations.
|
|
74
|
+
- Global topics that plausibly belong to a future blueprint and are NOT claimed by any shipped blueprint: `messageSerialisation` and `deliverySemantics` (a message-consumer blueprint's natural globals), `caching` (unclaimed by every shipped blueprint), `metricsExport` and `tracingProtocol` (natural globals for a metrics or tracing blueprint), `sessionStore` (unclaimed; a future session-persistence-committed blueprint's natural global). Define any of these in your own package's topics doc, in this file's format, and consider whether the band-registry table above needs your slug added.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# security-auth-keycloak guide
|
|
2
|
+
|
|
3
|
+
## What it is
|
|
4
|
+
|
|
5
|
+
A Keycloak-committed blueprint for delegated identity through OAuth2 authorisation-code with PKCE against a Keycloak realm the operator runs. It fixes the Keycloak-shaped decisions the vendor-neutral OAuth2 sibling deliberately leaves open: a Keycloak realm as the concrete issuer, JWKS-with-rotation-cache OR RFC 7662 introspection as the per-realm verification mode, the client-roles / realm-roles claim shape for role extraction, the local-first stand-up shape through the vendor's official container image, the fail-safe boot posture per realm, and the runtime-verify posture that binds against a real local Keycloak container without demanding a cloud tenant.
|
|
6
|
+
|
|
7
|
+
A project applies this blueprint, declares one or more realm-config records (each pointing at a Keycloak realm the operator runs), and inherits the discovery-driven endpoint record, the JWT verifier (or the introspection client), the role adapter, and the provider-routing seam. Adding a second realm is a config-record write plus a routeFn edit. The mechanism does not change.
|
|
8
|
+
|
|
9
|
+
## What it deliberately is not
|
|
10
|
+
|
|
11
|
+
Not a vendor-neutral blueprint. `security-auth-oauth2` is the sibling for projects that are not committed to a single vendor. This blueprint occupies the vendor-committed lane: the concrete Keycloak-shaped decisions (JWKS vs introspection, client-roles vs realm-roles, local container, RP-initiated logout through the realm's end_session_endpoint) are fixed here so the project code path names a Keycloak realm rather than an abstract provider record.
|
|
12
|
+
|
|
13
|
+
Not a hosted-identity blueprint. `security-auth-clerk` is the sibling for projects that want the vendor to host the sign-in surface, credential storage, MFA, and account recovery. This blueprint targets the operator who wants self-hosted control over the realm and the admin surface.
|
|
14
|
+
|
|
15
|
+
Not a passwordless-magic-link blueprint. `security-auth-magic-link` is the sibling for projects with no third-party identity dependency and the willingness to own the whole authentication surface in-house.
|
|
16
|
+
|
|
17
|
+
Not a flow-controller-contributing blueprint. The state machine that mints the pending-flow record, builds the authorisation redirect, and drives the callback is either the sibling `security-auth-oauth2` blueprint's TAC-1101 (compose the two blueprints, resolve the `authModel` global conflict to Keycloak, and point the oauth2 provider adapter at a Keycloak realm through this blueprint's discovery client and verifier) or a project-authored controller above this blueprint's five TACs. Either path is valid; the blueprint is honest that it contributes the Keycloak-shaped pieces, not the state machine.
|
|
18
|
+
|
|
19
|
+
Not a session-persistence blueprint. The session-bridge (in opaque-handle mode) injects the session-record store; the reference wiring is in-memory. A project that wants durable sessions composes `persistence-data-sqlite` (or `persistence-data-d1`) and points the store at a table. The blueprint does not commit the storage shape.
|
|
20
|
+
|
|
21
|
+
Not an MFA blueprint. MFA is the realm's concern; the blueprint delegates. A realm that requires MFA at the sign-in surface is transparent to the mechanism.
|
|
22
|
+
|
|
23
|
+
## When to reach for it
|
|
24
|
+
|
|
25
|
+
- The project has, or will run, a Keycloak realm; the ops posture prefers self-hosted identity over hosted-vendor identity.
|
|
26
|
+
- The project needs the Keycloak-specific decisions (JWKS-vs-introspection, client-roles-vs-realm-roles, RP-initiated logout) fixed at the mechanism layer so the project code path is Keycloak-shaped rather than provider-abstract.
|
|
27
|
+
- The project may have another OAuth2 or OIDC issuer alongside Keycloak (a second realm, a corporate issuer the middleware layer above this blueprint routes to) and wants the routing seam visible at one named point.
|
|
28
|
+
- The project wants runtime-verify to actually verify against a real Keycloak container in CI without demanding a cloud tenant.
|
|
29
|
+
- The project's ops team accepts running the Keycloak container as part of the deployment (either as a per-suite container in CI, a shared team-level container, or a production Kubernetes deployment).
|
|
30
|
+
|
|
31
|
+
## When it does not fit
|
|
32
|
+
|
|
33
|
+
- The project wants delegated identity but is not committed to one vendor. `security-auth-oauth2` is the shape.
|
|
34
|
+
- The project is committed to Clerk and wants the vendor to do more of the work than an OAuth2 record allows. `security-auth-clerk` is the shape.
|
|
35
|
+
- The project has no external IdP and no plan to obtain one, or the ops posture cannot run a Keycloak container. `security-auth-magic-link` is the shape.
|
|
36
|
+
- The project's session-verification requirements need statelessness at scale (no server-side session record). This blueprint supports that (ADR-1204's stateless mode) but the operator has to accept the per-request verification cost on every request; a project that prefers opaque-handle everywhere and can afford the store is on a smoother default.
|
|
37
|
+
|
|
38
|
+
## What a good outcome looks like
|
|
39
|
+
|
|
40
|
+
- One realm-config record per configured realm, on the fixed shape, validated at boot.
|
|
41
|
+
- The sign-in ceremony is the same code path across every configured realm; adding a realm is a record write plus a routeFn edit.
|
|
42
|
+
- Every access token either verifies (JWKS mode against a cached JWKS with kid-miss refresh; introspection mode against the RFC 7662 endpoint with optional short-lived cache) or refuses with a stable-coded reason.
|
|
43
|
+
- The browser holds an opaque-handle cookie (opaque-handle mode) or no session cookie at all (stateless mode); provider tokens live server-side (opaque-handle) or are re-verified per request (stateless); nothing on `request.auth` is a Keycloak-minted token.
|
|
44
|
+
- The provider-router seam is one named function; a reviewer inspecting the deployment can see the routing decision in one place.
|
|
45
|
+
- Refresh honours the realm's rotation model; a realm-signalled invalidation revokes the session cleanly.
|
|
46
|
+
- Sign-out clears the project session; the realm record's `providerLogout` flag decides realm-side redirect.
|
|
47
|
+
- `rcf audit coverage --strict` on the project's post-blueprint-apply state reports every blueprint AC as uncovered by TC (the blueprint ships no test files); every AC is a runtime-observable fact the project authors a TC against; the ship gate refuses on any uncovered AC that is not `accountBound`.
|
|
48
|
+
- The live cloud-realm smoke AC is `accountBound` and skipped by the runtime-verify runner when credentials are absent; the project-authored TC records the outcome honestly. The local-container smokes run every CI pass without any cloud dependency.
|
|
49
|
+
|
|
50
|
+
## Operator decisions that remain open after apply
|
|
51
|
+
|
|
52
|
+
- Which Keycloak realm(s) to configure. The blueprint runs against one realm, two realms, or N realms; the operator picks and declares each on a realm-config record.
|
|
53
|
+
- Where the `clientSecret` per record lives. The recommended pattern is a secret declared in the project's `secrets.yaml` (`security-secrets-management` composed) read at boot; a project that has not composed the secrets blueprint reads from its process environment or an equivalent.
|
|
54
|
+
- The verification mode per realm (`jwks` or `introspection`). Match the mode to the Keycloak client's configuration; a realm with a mix of client kinds gets one record per kind.
|
|
55
|
+
- The role claim shape per realm (`client-roles` or `realm-roles`). Match to the realm's client configuration; the choice is legible on the record.
|
|
56
|
+
- The session mode per realm (`opaque-handle` or `stateless`). Default is opaque-handle; stateless is opt-in for deployments where a session store is undesirable.
|
|
57
|
+
- The boot posture per realm (`strict`, `deferred`, or `standby`). Default is strict; the operator picks based on deployment shape.
|
|
58
|
+
- The JWKS cache TTL per realm. Default 900 seconds; the operator raises or lowers per the realm's rotation cadence and the project's staleness tolerance.
|
|
59
|
+
- The provider-router routeFn. A single-realm deployment uses the reference constant; a multi-realm or issuer-hand-off deployment writes its own.
|
|
60
|
+
- The Keycloak container tag. The operator pins the currently-supported stable at harness-setup time and upgrades on the vendor's cadence.
|
|
61
|
+
- The `enrichPrincipal` hook. Empty roles and organisationIds arrays are the default (with the raw Keycloak role strings on `roles[]`); a project that maps Keycloak roles onto project-role vocabulary authors the hook and lists the mapping in a project-level ADR.
|
|
62
|
+
- The live cloud-realm smoke. AC-11112-2 is `accountBound`; a project that has live credentials wires them and the TC lights up, otherwise the skip is honest.
|
|
63
|
+
|
|
64
|
+
## Cost honesty
|
|
65
|
+
|
|
66
|
+
Shipping this doc set costs the project 12 REQs, 13 USs (34 ACs), 5 TACs, and 6 ADRs on the tree; the ACs are runtime-observable and the project's build cycle owns writing the TCs. The realisation cost is one discovery client, one JWT verifier (JWKS mode), one introspection client (opaque mode), one provider router, one role adapter, and (per the composition choice) either the sibling `security-auth-oauth2` blueprint's flow controller wired to a Keycloak realm or a project-authored flow controller above the five TACs. The reference wiring runs to a small number of files in one package. The Keycloak container is a one-off harness dependency the operator stands up per the local-container asset; runtime-verify against it is free of cloud cost. The live cloud-realm smoke costs the operator credentials on a project-owned Keycloak deployment; that cost is unavoidable and the `accountBound` posture keeps it out of CI.
|
|
67
|
+
|
|
68
|
+
## Promotion signals to the other siblings
|
|
69
|
+
|
|
70
|
+
- The project outgrows self-hosting and wants a hosted vendor to run the sign-in surface, credential storage, MFA, and account recovery. Promote to `security-auth-clerk`: supersede ADR-1201 with a project-level ADR pointing at Clerk's authModel; apply `security-auth-clerk`; retire the Keycloak container.
|
|
71
|
+
- The project needs delegated identity that is not vendor-committed (a small project that wants to plug in Google or GitHub without running a realm). Demote to `security-auth-oauth2`: supersede ADR-1201 with a project-level ADR pointing at oauth2's authModel; apply `security-auth-oauth2`.
|
|
72
|
+
- The project's audience needs a passwordless-magic-link posture (regulated environment, no third-party identity dependency). Demote to `security-auth-magic-link`.
|
|
73
|
+
|
|
74
|
+
## Provider-aware install-design shape (Baz-reshape, restated)
|
|
75
|
+
|
|
76
|
+
The blueprint stays Keycloak-committed. What the blueprint does NOT do is assume Keycloak is the only issuer the receiving system will ever consult. Two shapes make this explicit:
|
|
77
|
+
|
|
78
|
+
- The provider-router seam (TAC-1204, ADR-1203) exposes one named point in the request-processing chain where a project's own middleware makes the routing decision. A project with only Keycloak wires the seam to a constant; a project with two Keycloak realms wires the seam to pick between them per request marker; a project with Keycloak alongside another OAuth2 or OIDC issuer above this blueprint's mechanism reach returns the sentinel `notThisIssuer` and the middleware layer above owns the request.
|
|
79
|
+
- The introspection path (REQ-004, TAC-1203) speaks the RFC 7662 shape whether the issuer is Keycloak or another conforming server; a project that has chosen to consult a non-Keycloak issuer at the introspection seam does not need a new vocabulary.
|
|
80
|
+
|
|
81
|
+
The blueprint refuses to name any specific second issuer, any specific request marker, or any specific dual-provider deployment shape. Those are project-level decisions the operator authors on a project-side ADR whose `related-reqs` cites REQ-005 and ADR-1203.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Auth blueprint (v1.0.0)
|
|
2
|
+
|
|
3
|
+
The third content blueprint on the rcf-build-lite blueprint mechanism (design brief v2, ratified; Phase 4 of the blueprint programme). Scope: passwordless magic-link sign-in with server-issued opaque cookie sessions, single deployable, pluggable email delivery and pluggable principal registry, targeted at small greenfield rcf-lite projects. Composes with the application-spa blueprint (client half) and the application-api-rest blueprint (server half) by design, contributing one deliberate scope:global conflict on `authModel`.
|
|
4
|
+
|
|
5
|
+
## Apply
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
rcf define blueprint add <path-to>/blueprints/security-auth-magic-link
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Phase 1 resolves local path sources only; registry and git-ref resolution is a mechanism follow-up. Apply is idempotent; `rcf define blueprint list` shows the applied entry; `rcf define blueprint remove security-auth-magic-link` cleanly removes an unreferenced application.
|
|
12
|
+
|
|
13
|
+
## Anatomy
|
|
14
|
+
|
|
15
|
+
| Piece | Where | What |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| Metadata | `blueprint.json` | Slug, version, and the 32 contributions with scope/topic on the one global ADR |
|
|
18
|
+
| Doc set | `contributions/` | 11 REQs, 11 USs (37 ACs), 5 TACs, 5 ADRs, all schema-valid against rcf-schemas 0.4.5 and namespaced (`security-auth-magic-link-REQ-001` prefix family; `ADR-501-security-auth-magic-link-model` suffix family) |
|
|
19
|
+
| Email templates | `assets/email-templates/magic-link-email.md` | The text and HTML bodies the routes hand to the adapter for magic-link delivery, with placeholders for base URL, token URL, and expiry window |
|
|
20
|
+
| Stub adapter reference | `assets/email-templates/stub-adapter.md` | The record-only stub the blueprint ships for tests, with the exact call log shape and outcome shape |
|
|
21
|
+
| Principal registry samples | `assets/principal-registry-samples/single-address.md` | The single-address registry implementation for solo-operator deployments |
|
|
22
|
+
| Principal registry samples | `assets/principal-registry-samples/allow-list-file.md` | An allow-list file registry pattern for small teams |
|
|
23
|
+
| Guide | `guide/security-auth-magic-link.md` | Operator-facing: when to use it, when not, what stays your call, and the promotion signal for the future auth-oidc blueprint |
|
|
24
|
+
| Coordination vocabulary | `docs/topics.md` | The one global-topic string this blueprint contributes, the shared id band registry (application-spa, application-api-rest, security-auth-magic-link, hello-panel, persistence-data-sqlite, ci-pipeline, observability-essentials) |
|
|
25
|
+
|
|
26
|
+
The doc set is contributions (copied into the project tree by `rcf define blueprint add`); the guide, assets, and docs are package-resident references. Guide rendering into `rcf/knowledge/docs/blueprint-guides/` and asset ingestion are mechanism follow-ups; until they land, the working agent reads them from the applied blueprint's source path recorded in `manifest.blueprints[].source`.
|
|
27
|
+
|
|
28
|
+
## What it contributes, and what it deliberately does not
|
|
29
|
+
|
|
30
|
+
Contributed kinds: REQ, US (with inline ACs), TAC, ADR. Adherence is expressed as ACs; the blueprint ships no test files (ratified decision 5) and no code.
|
|
31
|
+
|
|
32
|
+
No FBS contributions, as a matter of principle (ratified policy 2026-08-19): FBSs are the work of the implementing agent, not the blueprint; project constraints have to be applied at the time of creation. The blueprint contributes the WHAT (the sign-in flow, the token lifecycle, the session lifecycle, the two pluggable interfaces); the implementing agent derives the HOW-tasks (FBS) in the host project, where the ACs contributed here get picked up by the project's own build sequencing.
|
|
33
|
+
|
|
34
|
+
Deliberately not contributed: authorisation (roles, permissions, tenancy) is a project concern that layers above the session record's principal id, not inside this blueprint; multi-factor authentication is a project concern that layers on top of a resolved session; federated identity (OIDC, SAML) is a future auth-oidc blueprint (see guide 'when it does not fit'); email transport is a project concern behind the pluggable adapter contract; principal registry shape is a project concern behind the pluggable lookup contract.
|
|
35
|
+
|
|
36
|
+
## The one global decision
|
|
37
|
+
|
|
38
|
+
ADR-501-security-auth-magic-link-model ships `scope: global` on topic `authModel`. This is the third half of the project-level authentication model; application-spa contributes ADR-205-application-spa-auth-model on the same topic (the client half: cookie-based sessions, 401-redirect posture), application-api-rest contributes ADR-302-application-api-rest-auth-model on the same topic (the server half: four declared auth classes enforced in middleware). Applying any two of the three on one project surfaces the pairing for operator resolution, which is the composition mechanism doing its job. See `docs/topics.md` for the exact strings, the expected resolutions, and the AC id band allocation (security-auth-magic-link owns 3101-3899).
|
|
39
|
+
|
|
40
|
+
## Quality bar
|
|
41
|
+
|
|
42
|
+
Passwordless sign-in via emailed one-shot URL; single-use time-limited tokens with a fifteen-minute default expiry and remint-invalidates-predecessors; server-issued opaque handles of at least 24 bytes of entropy with no JWT-shaped payload; Secure HttpOnly SameSite=Lax cookie transport; server-side revocation on sign-out and administrative revoke-all-for-principal; anti-enumeration on the sign-in submission (byte-identical body, identical status, wall-clock timing floor); rate-limited mint and consume endpoints with honest Retry-After; session and token persistence across process restart; structured auth event log with zero secret leakage; pluggable email delivery adapter behind a narrow contract; pluggable principal registry behind a narrow contract. Every bar is carried by ACs in the doc set, not by this README.
|
|
43
|
+
|
|
44
|
+
## Known mechanism-reach gaps
|
|
45
|
+
|
|
46
|
+
None at v1.0.0. Every AC on every story is bound to at least one TAC that the host project must realise, and every AC's `then` clause is runtime-observable in the deployed application (Set-Cookie inspection, response body byte-comparison, adapter-call enumeration, event-log field scanning). The mechanism-reach principle from the authoring standard section 7 is satisfied at ship: a project that applies this blueprint and does not realise a TAC leaves an unresolved `tacIds` reference on the story that `rcf define validate` and `rcf audit coverage` refuse. The one operational surface a project must own on its own is the durable store implementation the two managers depend on (security-auth-magic-link-REQ-008); that responsibility is stated as a TAC dependency, not as a smuggled runtime probe.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Magic-link email template
|
|
2
|
+
|
|
3
|
+
Two bodies, one subject. The routes compose `{{ signInUrl }}` from the deployment base URL, `/login/verify`, and the minted token; the routes pass `{{ expiryWindow }}` as the token's expiry in a human phrase (default: 'fifteen minutes'). The adapter receives all four fields on every call.
|
|
4
|
+
|
|
5
|
+
## Subject
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Sign in to {{ appName }}
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Text body
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Someone (hopefully you) asked to sign in to {{ appName }}.
|
|
15
|
+
|
|
16
|
+
Follow this link within the next {{ expiryWindow }} to complete the sign-in:
|
|
17
|
+
|
|
18
|
+
{{ signInUrl }}
|
|
19
|
+
|
|
20
|
+
The link is single-use and expires. If you did not request a sign-in, ignore
|
|
21
|
+
this email; the link will do nothing on its own.
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## HTML body
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<!doctype html>
|
|
28
|
+
<html>
|
|
29
|
+
<body>
|
|
30
|
+
<p>Someone (hopefully you) asked to sign in to {{ appName }}.</p>
|
|
31
|
+
<p>
|
|
32
|
+
Follow this link within the next {{ expiryWindow }} to complete the sign-in:
|
|
33
|
+
<br>
|
|
34
|
+
<a href="{{ signInUrl }}">{{ signInUrl }}</a>
|
|
35
|
+
</p>
|
|
36
|
+
<p>
|
|
37
|
+
The link is single-use and expires. If you did not request a sign-in,
|
|
38
|
+
ignore this email; the link will do nothing on its own.
|
|
39
|
+
</p>
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Both bodies name the same URL. The plaintext copy is what the email adapter's provider is most likely to render for spam-scoring and preview purposes; keep them in sync.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Stub email adapter
|
|
2
|
+
|
|
3
|
+
The blueprint's TAC-504 names a stub-adapter implementation that projects wire into their test harness in place of the real transport. The stub records every outgoing call in memory and resolves the fixed outcome below; nothing leaves the process.
|
|
4
|
+
|
|
5
|
+
## Interface satisfied
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
send({ to, subject, textBody, htmlBody })
|
|
9
|
+
-> Promise<{ ok, providerStatus, providerMessageId, error }>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Fixed outcome (successful case)
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"ok": true,
|
|
17
|
+
"providerStatus": 200,
|
|
18
|
+
"providerMessageId": "stub",
|
|
19
|
+
"error": null
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Fixed outcome (failing case)
|
|
24
|
+
|
|
25
|
+
Constructed by the test with an override:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"ok": false,
|
|
30
|
+
"providerStatus": 502,
|
|
31
|
+
"providerMessageId": null,
|
|
32
|
+
"error": "stub configured to fail: <reason>"
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## In-memory call log shape
|
|
37
|
+
|
|
38
|
+
The stub exposes `sends`, an array of every call in the order received:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
[
|
|
42
|
+
{
|
|
43
|
+
"to": "operator@example.com",
|
|
44
|
+
"subject": "Sign in to demo-app",
|
|
45
|
+
"textBody": "Someone (hopefully you) asked ...",
|
|
46
|
+
"htmlBody": "<!doctype html>..."
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Tests assert on `sends[0].to`, `sends[0].textBody.includes(signInUrl)`, and `sends.length === 1` per AC-3110-3 and AC-3101-3.
|
|
52
|
+
|
|
53
|
+
## Do not use in production
|
|
54
|
+
|
|
55
|
+
The stub is a test surface. Loading the stub in a production build defeats the sign-in flow silently: mint succeeds, the recipient never receives a link, the anti-enumeration budget hides the failure from the response, and only the `adapterSendFailed` event log entry names the problem (and even then, only if a real send would have failed; a stub records success). A project's deployment config forbids the stub adapter's module name in production; see the project's own configuration ADR for the mechanism.
|
package/blueprints/security-auth-magic-link/assets/principal-registry-samples/allow-list-file.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Allow-list-file principal registry (project-authored pattern)
|
|
2
|
+
|
|
3
|
+
A common step past the single-address registry: a static file on disk holding the registered set, one address per line. The blueprint does not ship this implementation, but the pattern below is what most small teams end up with before they need a database.
|
|
4
|
+
|
|
5
|
+
## Interface satisfied
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
isRegistered(email) -> Promise<boolean>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
The project supplies one field:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"registeredEmailsFile": "/etc/app/registered-emails.txt"
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## File format
|
|
22
|
+
|
|
23
|
+
Plain text, one address per line, ignored:
|
|
24
|
+
|
|
25
|
+
- lines that start with `#` (comments)
|
|
26
|
+
- empty lines
|
|
27
|
+
- surrounding whitespace on each address
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
# Registered operators; edit and restart the app to apply.
|
|
33
|
+
operator@example.com
|
|
34
|
+
teammate@example.com
|
|
35
|
+
|
|
36
|
+
# On-call cover
|
|
37
|
+
oncall@example.com
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Behaviour
|
|
41
|
+
|
|
42
|
+
The registry reads the file once at start (or reloads on a project-owned signal) and holds the trimmed lowercase set in memory. `isRegistered(email)` returns true when the trimmed lowercase form of `email` is in the set, false otherwise.
|
|
43
|
+
|
|
44
|
+
## Why the blueprint does not ship it
|
|
45
|
+
|
|
46
|
+
Two reasons. First, the reload story is project-specific: some projects want a SIGHUP reload, some want a filesystem watcher, some want a restart-required posture. Second, the file location and permissions are project deployment concerns; hardcoding `/etc/app/...` in the blueprint is a WESPA leak of exactly the shape the authoring standard's provenance rule forbids. The blueprint documents the pattern here so a project writing it does not reinvent the shape.
|
package/blueprints/security-auth-magic-link/assets/principal-registry-samples/single-address.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Single-address principal registry
|
|
2
|
+
|
|
3
|
+
The blueprint's TAC-505 ships one registry implementation: a single-address lookup for solo-operator deployments. The project supplies one email string at configuration time; the registry returns true only for that email (compared case-insensitively after trimming whitespace) and false for every other input.
|
|
4
|
+
|
|
5
|
+
## Interface satisfied
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
isRegistered(email) -> Promise<boolean>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
The project supplies one field:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"registeredEmail": "operator@example.com"
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Behaviour table
|
|
22
|
+
|
|
23
|
+
| Input | Resolved |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `operator@example.com` | `true` |
|
|
26
|
+
| `Operator@Example.COM` | `true` (case-insensitive) |
|
|
27
|
+
| ` operator@example.com ` | `true` (whitespace trimmed) |
|
|
28
|
+
| `other@example.com` | `false` |
|
|
29
|
+
| `""` | `false` |
|
|
30
|
+
| `null` or `undefined` | `false` |
|
|
31
|
+
| `"not-an-email"` | `false` (registry does not validate shape, but no match means false) |
|
|
32
|
+
|
|
33
|
+
## Why it exists
|
|
34
|
+
|
|
35
|
+
The rcf-lite tier this blueprint targets includes solo-operator projects (watchpost, personal dashboards, single-tenant admin surfaces). The single-address registry is the smallest useful implementation and demonstrates the boolean-only shape of the contract; projects that scale past one operator write their own allow-list-file or database-lookup implementation, keeping the same interface.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"slug": "security-auth-magic-link",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"category": "security",
|
|
5
|
+
"contributions": [
|
|
6
|
+
{ "id": "security-auth-magic-link-REQ-001", "kind": "req", "path": "requirements/security-auth-magic-link-req-001.json" },
|
|
7
|
+
{ "id": "security-auth-magic-link-REQ-002", "kind": "req", "path": "requirements/security-auth-magic-link-req-002.json" },
|
|
8
|
+
{ "id": "security-auth-magic-link-REQ-003", "kind": "req", "path": "requirements/security-auth-magic-link-req-003.json" },
|
|
9
|
+
{ "id": "security-auth-magic-link-REQ-004", "kind": "req", "path": "requirements/security-auth-magic-link-req-004.json" },
|
|
10
|
+
{ "id": "security-auth-magic-link-REQ-005", "kind": "req", "path": "requirements/security-auth-magic-link-req-005.json" },
|
|
11
|
+
{ "id": "security-auth-magic-link-REQ-006", "kind": "req", "path": "requirements/security-auth-magic-link-req-006.json" },
|
|
12
|
+
{ "id": "security-auth-magic-link-REQ-007", "kind": "req", "path": "requirements/security-auth-magic-link-req-007.json" },
|
|
13
|
+
{ "id": "security-auth-magic-link-REQ-008", "kind": "req", "path": "requirements/security-auth-magic-link-req-008.json" },
|
|
14
|
+
{ "id": "security-auth-magic-link-REQ-009", "kind": "req", "path": "requirements/security-auth-magic-link-req-009.json" },
|
|
15
|
+
{ "id": "security-auth-magic-link-REQ-010", "kind": "req", "path": "requirements/security-auth-magic-link-req-010.json" },
|
|
16
|
+
{ "id": "security-auth-magic-link-REQ-011", "kind": "req", "path": "requirements/security-auth-magic-link-req-011.json" },
|
|
17
|
+
{ "id": "security-auth-magic-link-US-3101", "kind": "us", "path": "user-stories/security-auth-magic-link-us-3101.json" },
|
|
18
|
+
{ "id": "security-auth-magic-link-US-3102", "kind": "us", "path": "user-stories/security-auth-magic-link-us-3102.json" },
|
|
19
|
+
{ "id": "security-auth-magic-link-US-3103", "kind": "us", "path": "user-stories/security-auth-magic-link-us-3103.json" },
|
|
20
|
+
{ "id": "security-auth-magic-link-US-3104", "kind": "us", "path": "user-stories/security-auth-magic-link-us-3104.json" },
|
|
21
|
+
{ "id": "security-auth-magic-link-US-3105", "kind": "us", "path": "user-stories/security-auth-magic-link-us-3105.json" },
|
|
22
|
+
{ "id": "security-auth-magic-link-US-3106", "kind": "us", "path": "user-stories/security-auth-magic-link-us-3106.json" },
|
|
23
|
+
{ "id": "security-auth-magic-link-US-3107", "kind": "us", "path": "user-stories/security-auth-magic-link-us-3107.json" },
|
|
24
|
+
{ "id": "security-auth-magic-link-US-3108", "kind": "us", "path": "user-stories/security-auth-magic-link-us-3108.json" },
|
|
25
|
+
{ "id": "security-auth-magic-link-US-3109", "kind": "us", "path": "user-stories/security-auth-magic-link-us-3109.json" },
|
|
26
|
+
{ "id": "security-auth-magic-link-US-3110", "kind": "us", "path": "user-stories/security-auth-magic-link-us-3110.json" },
|
|
27
|
+
{ "id": "security-auth-magic-link-US-3111", "kind": "us", "path": "user-stories/security-auth-magic-link-us-3111.json" },
|
|
28
|
+
{ "id": "TAC-501-security-auth-magic-link-manager", "kind": "tac", "path": "tacs/tac-501-security-auth-magic-link-manager.json" },
|
|
29
|
+
{ "id": "TAC-502-security-auth-magic-link-session-manager", "kind": "tac", "path": "tacs/tac-502-security-auth-magic-link-session-manager.json" },
|
|
30
|
+
{ "id": "TAC-503-security-auth-magic-link-login-routes", "kind": "tac", "path": "tacs/tac-503-security-auth-magic-link-login-routes.json" },
|
|
31
|
+
{ "id": "TAC-504-security-auth-magic-link-email-delivery-adapter", "kind": "tac", "path": "tacs/tac-504-security-auth-magic-link-email-delivery-adapter.json" },
|
|
32
|
+
{ "id": "TAC-505-security-auth-magic-link-principal-registry", "kind": "tac", "path": "tacs/tac-505-security-auth-magic-link-principal-registry.json" },
|
|
33
|
+
{
|
|
34
|
+
"id": "ADR-501-security-auth-magic-link-model",
|
|
35
|
+
"kind": "adr",
|
|
36
|
+
"path": "adrs/adr-501-security-auth-magic-link-model.json",
|
|
37
|
+
"scope": "global",
|
|
38
|
+
"topic": "authModel"
|
|
39
|
+
},
|
|
40
|
+
{ "id": "ADR-502-security-auth-magic-link-token-secrecy", "kind": "adr", "path": "adrs/adr-502-security-auth-magic-link-token-secrecy.json" },
|
|
41
|
+
{ "id": "ADR-503-security-auth-magic-link-anti-enumeration-budget", "kind": "adr", "path": "adrs/adr-503-security-auth-magic-link-anti-enumeration-budget.json" },
|
|
42
|
+
{ "id": "ADR-504-security-auth-magic-link-session-lifecycle", "kind": "adr", "path": "adrs/adr-504-security-auth-magic-link-session-lifecycle.json" },
|
|
43
|
+
{ "id": "ADR-505-security-auth-magic-link-rate-limiting", "kind": "adr", "path": "adrs/adr-505-security-auth-magic-link-rate-limiting.json" }
|
|
44
|
+
]
|
|
45
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-501-security-auth-magic-link-model",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Passwordless magic-link sign-in with server-issued opaque cookie sessions as the project's authentication model",
|
|
8
|
+
"context": "A project has one authentication model; the client tier, the server tier, and every operator surface must reason against it. The security-auth-magic-link blueprint contributes the third half of the model: how an operator actually gets through the door, and what shape the session takes on the wire once they have. A client-tier blueprint (SPA) and a server-tier blueprint (REST) applied to the same project contribute their own decisions on this topic, and blueprint composition surfaces the pairing at add time for the operator to reconcile into one project-level model. That surfacing is intended.",
|
|
9
|
+
"decision": "Sign-in is passwordless: the operator submits their email to POST /login, the server mints a single-use time-limited token when the address is a registered principal, and the sign-in URL carrying the token is delivered by a pluggable email adapter. GET /login/verify consumes the token and issues a session. The session is a server-side record; the credential the operator's browser holds is an opaque base64url handle of at least 24 bytes of entropy, transported in a Secure HttpOnly SameSite=Lax cookie. No password field exists on any surface; no JWT-shaped self-describing token is issued on any code path.",
|
|
10
|
+
"consequences": "The project owns email delivery through the adapter interface and owns the principal registry through the isRegistered contract. Revocation is a server-side delete on the session record; 'sign me out everywhere' is one call. XSS cannot exfiltrate the credential because the handle is HttpOnly. CSRF has a SameSite=Lax floor and the project layers whatever extra token defence the application-spa and application-api-rest halves agree on. Composing with a client-tier or server-tier blueprint deliberately conflicts on this topic; the expected resolution is one project-level ADR that fixes the credential shape (this ADR's opaque cookie session), maps it onto the server's auth classes (the application-api-rest blueprint's four classes if applied), and specifies how the client half handles session expiry (the application-spa blueprint's cookie session and 401-redirect posture if applied).",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Password + hashed store",
|
|
14
|
+
"summary": "Operators register a password, the server stores a hash, the sign-in form takes email plus password.",
|
|
15
|
+
"reasonNotChosen": "The blueprint owns the sign-in flow; password handling brings hashing choice, rotation policy, breach-check integration, and reset flows every project has to build correctly to be safe. For the rcf-lite tier a passwordless flow removes the credential the operator must remember and keeps the secret material server-owned and short-lived."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Federated OIDC through an external identity provider",
|
|
19
|
+
"summary": "Delegate authentication to a Keycloak-local or hosted identity provider through the OIDC authorization-code flow.",
|
|
20
|
+
"reasonNotChosen": "Valid where an external IdP is a project requirement (multi-tenant identity, role management, group memberships). For a small greenfield rcf-lite project the container plus realm configuration cost outweighs the benefit; that model belongs in a future 'auth-oidc' blueprint aimed at bigger projects. See guide 'when it does not fit' for the promotion signal."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "Signed JWT bearer tokens in a client-readable header or storage",
|
|
24
|
+
"summary": "Issue a self-describing bearer on sign-in that the client attaches to every request.",
|
|
25
|
+
"reasonNotChosen": "Script-readable credentials fail security-auth-magic-link-REQ-004's transport floor; opaque handle plus server record is cheaper to revoke and safer under XSS. Projects that need bearer transport (native clients, service-to-service) layer a project-level ADR superseding the transport half."
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"createdAt": "2026-08-21T00:00:00Z",
|
|
29
|
+
"updatedAt": "2026-08-21T00:00:00Z"
|
|
30
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-502-security-auth-magic-link-token-secrecy",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Sign-in tokens and session handles are opaque secrets that never appear in logs or on client-readable surfaces",
|
|
8
|
+
"context": "Two credential-shaped values exist inside the auth flow: the sign-in token (short-lived, single-use) and the session handle (long-lived, revocable). Both are secrets. Either one leaking into a log line, a metric label, an error message, or a client-visible response body reintroduces the class of failures the flow's design forbids. The project's observability stack cannot be trusted to redact after the fact; the discipline has to be enforced at emit time.",
|
|
9
|
+
"decision": "Sign-in tokens and session handles are opaque strings the auth layer holds only long enough to complete their operation. The token secret exists as plaintext only as the return of magicLinkManager.mint and the argument to magicLinkManager.consume; the session handle exists as plaintext only inside the cookie value the response sets and the cookie header the next request presents. Neither value appears in any structured-log field, any metric label, any span attribute, any error message body, or any response body other than the Set-Cookie header for the session handle. The magic-link event log fields carry the principal id, the expiresAt timestamp, and the outcome; the session event log fields carry the principal id, the outcome, and where relevant the reason for invalidation. Nothing else.",
|
|
10
|
+
"consequences": "The events log is safe to ship to third-party observability providers because it holds no credential material; a log store breach is not a session-takeover breach. Providers that need per-session correlation for debugging must derive their correlation id from something other than the handle (a request id is the intended surface). Error messages surfaced to the operator confirm success or failure but never quote credential material back at them.",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Log token and handle values under a redaction rule at the log shipper",
|
|
14
|
+
"summary": "Emit secrets structured and rely on a downstream redactor.",
|
|
15
|
+
"reasonNotChosen": "Redactors miss cases (new field, misspelled field, escaped value), and the log is already on disk by the time the redactor runs. Not-emitting-in-the-first-place is the only reliable posture."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Emit hashed token and handle values",
|
|
19
|
+
"summary": "Log a stable hash so investigations can correlate without exposing the plaintext.",
|
|
20
|
+
"reasonNotChosen": "A hashed handle still lets an attacker with log access confirm 'this handle is the handle for that principal', which is enough for correlation attacks. The request id already provides the correlation surface without leaking anything."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"createdAt": "2026-08-21T00:00:00Z",
|
|
24
|
+
"updatedAt": "2026-08-21T00:00:00Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-503-security-auth-magic-link-anti-enumeration-budget",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "POST /login enforces a uniform response body, status, and wall-clock timing floor against enumeration",
|
|
8
|
+
"context": "A sign-in submission handler that differentiates its behaviour on the basis of principal registration hands attackers a free enumeration oracle: an attacker with a wordlist harvests the registered set by watching for any observable difference between 'this address is registered' and 'this address is not'. The three surfaces that leak this signal are the response body, the response status, and the wall-clock latency; a defence has to close all three.",
|
|
9
|
+
"decision": "POST /login returns byte-identical response bodies and identical HTTP statuses (200) across registered, unregistered, malformed, and empty submissions that are not rate-limited. Rate-limited responses (429) are also identical across principals. A per-handler anti-enumeration budget enforces a wall-clock floor on the response: the handler never returns earlier than the budget, regardless of code path. The budget is a configurable millisecond value with a default of 800; the default is set to comfortably dominate the slowest legitimate branch (mint plus adapter send on a typical email provider). Adapter-send failures are caught inside the budget and surfaced only via the event log, never via the response.",
|
|
10
|
+
"consequences": "The endpoint is not an enumeration oracle: a submission for a random address looks exactly like a submission for the operator's actual address. Legitimate operator retries pay the budget as latency every time; the budget is deliberately noticeable to raise the cost of high-volume mint sprays. The event log is the only surface where the registered-versus-unregistered distinction is observable, and the log is a server-owned surface.",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Different bodies with the same status and timing",
|
|
14
|
+
"summary": "Return a body that names the failure reason for unregistered submissions but keeps the timing floor uniform.",
|
|
15
|
+
"reasonNotChosen": "The body is exactly the enumeration signal the design closes; keeping timing uniform while leaking the answer in the body defeats the point."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Rate-limit only, no timing floor",
|
|
19
|
+
"summary": "Rely on a tight rate limit to keep enumeration expensive without introducing latency for legitimate operators.",
|
|
20
|
+
"reasonNotChosen": "Rate limits per client key are worked around by attackers rotating client keys (residential proxies, botnets). The timing floor is uniform per request and does not depend on the attacker's shape."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"createdAt": "2026-08-21T00:00:00Z",
|
|
24
|
+
"updatedAt": "2026-08-21T00:00:00Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-504-security-auth-magic-link-session-lifecycle",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Sessions carry a sliding idle window, a fixed absolute lifetime, and server-side revocation as the only invalidation truth",
|
|
8
|
+
"context": "A session has three lifetime axes: how long it can be idle before it invalidates, how long it can live in absolute wall-clock terms regardless of activity, and how quickly a revoke can end it on demand. Every axis has to be a server-side decision because the client cannot be trusted to end its own session honestly; a session that only ends when the browser forgets its cookie is a session an attacker with the cookie can still ride.",
|
|
9
|
+
"decision": "Every session record carries a lastSeenAt timestamp and an absoluteExpiresAt timestamp. The sliding idle window is fifteen minutes by default (900000 ms); validateSession invalidates any record whose lastSeenAt is older than the idle window and refreshes lastSeenAt on every valid request. The absolute lifetime is thirty days by default (2592000000 ms); validateSession invalidates any record whose absoluteExpiresAt is in the past, regardless of activity. invalidateSession(handle) deletes the record; revokeAllForPrincipal(principalId) deletes every record for the principal in one call. Both defaults are constructor options; project overrides update the ADR's consequences in a project-level ADR.",
|
|
10
|
+
"consequences": "A stolen cookie has at most fifteen minutes of inactivity before it stops working; if the operator uses the session actively, the sliding window can extend to the absolute ceiling of thirty days. 'Sign me out everywhere' is one revokeAllForPrincipal call. Sessions survive process restart because the store is durable; the idle clock counts wall-clock elapsed during a restart against the window, so a long-stopped process does not falsely refresh sessions. Projects with tighter operator-lifetime needs (regulated environments, shared devices) supersede the defaults in a project-level ADR.",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Absolute expiry only, no sliding window",
|
|
14
|
+
"summary": "One expiry ceiling per session, no per-request refresh.",
|
|
15
|
+
"reasonNotChosen": "Every long-lived operator hits the ceiling mid-work and pays a forced sign-in. The sliding window keeps active operators signed in without extending the absolute ceiling."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Sliding window only, no absolute ceiling",
|
|
19
|
+
"summary": "Sessions live forever as long as the operator uses them.",
|
|
20
|
+
"reasonNotChosen": "Fails 'sessions rotate on a bounded schedule' expectations; an absolute ceiling caps blast-radius for a session record whose creation the operator no longer remembers."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "Client-side expiry (the cookie's Max-Age carries the truth)",
|
|
24
|
+
"summary": "Rely on the browser to stop presenting an expired cookie.",
|
|
25
|
+
"reasonNotChosen": "The server has to enforce every session decision because the client cannot be trusted; a cookie's Max-Age helps browser hygiene but is never the invalidation surface."
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"createdAt": "2026-08-21T00:00:00Z",
|
|
29
|
+
"updatedAt": "2026-08-21T00:00:00Z"
|
|
30
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-505-security-auth-magic-link-rate-limiting",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Per-endpoint rate limits with honest Retry-After on the sign-in mint and consume paths",
|
|
8
|
+
"context": "Two auth endpoints attract abuse. POST /login is a mint endpoint that an unbounded caller turns into an email-flooding pipeline aimed at the operator's own inbox. GET /login/verify is a consume endpoint that an unbounded caller turns into a brute-force pipeline against the token space. Both need ceilings low enough to make the abuse economically uninteresting without tripping on legitimate operator retry patterns.",
|
|
9
|
+
"decision": "POST /login is rate-limited to five requests per minute per client key by default. GET /login/verify is rate-limited to twenty requests per minute per client key by default. Both endpoints emit HTTP 429 on breach with a Retry-After header carrying a positive integer or a valid HTTP-date at or after the request time. 429 responses do not disclose registration state; the body is generic and identical across principals. Ceilings and windows are project-configurable options on the routes composition; overrides update the numbers stated in the project-level ADR that supersedes rate posture. The client key derivation defaults to the request's client IP (via the framework's rate-limit plugin); projects behind a trusted proxy configure the plugin to derive from a forwarded-for header instead.",
|
|
10
|
+
"consequences": "Legitimate operator sign-in retries stay well under the ceiling. A mint spray is stopped inside the first minute per client key; a token-guessing sweep is stopped inside the same window. Retry-After is honest, so well-behaved clients back off predictably; badly behaved clients are shed by the plugin without cost to the auth code. Projects with heavier legitimate load (shared IP behind NAT, corporate proxy) raise the ceilings and state the trade in a project-level ADR.",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Global rate limit only",
|
|
14
|
+
"summary": "One ceiling across the whole service.",
|
|
15
|
+
"reasonNotChosen": "A global limit trades a legitimate operator's sign-in against every other endpoint; the sign-in endpoints have their own abuse pattern and deserve their own ceiling."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "No rate limit; rely on external WAF",
|
|
19
|
+
"summary": "Assume the deploy target puts a WAF in front of the service.",
|
|
20
|
+
"reasonNotChosen": "The blueprint targets small greenfield deployments where a WAF is not a given; making rate-limits the service's own responsibility means the floor holds without external infrastructure."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"createdAt": "2026-08-21T00:00:00Z",
|
|
24
|
+
"updatedAt": "2026-08-21T00:00:00Z"
|
|
25
|
+
}
|