rcf-lite 0.0.1 → 0.7.1
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 +288 -0
- package/LICENSE +202 -0
- package/README.md +92 -4
- package/bin/rcf-verify.js +122 -0
- package/bin/rcf.js +174 -0
- package/bin/view-supervisor-child.mjs +14 -0
- package/fixtures/canary-manifest.json +103 -0
- package/guidance/README.md +25 -0
- package/guidance/build-cycle-playbook.md +492 -0
- package/guidance/build-cycle.md +40 -0
- package/guidance/document-model.md +45 -0
- package/guidance/elicitation-playbook.md +442 -0
- package/guidance/harness-template.md +246 -0
- package/guidance/managed/README.md +63 -0
- package/guidance/managed/agent-instructions-block.hash +1 -0
- package/guidance/managed/agent-instructions-block.md +220 -0
- package/guidance/managed/legacy-fragment-hashes.json +22 -0
- package/guidance/manifest.json +21 -0
- package/guidance/overview.md +48 -0
- package/guidance/persona-programme.md +44 -0
- package/package.json +69 -8
- package/rcf/adrs/adr-001.json +25 -0
- package/rcf/adrs/adr-002.json +25 -0
- package/rcf/adrs/adr-003.json +25 -0
- package/rcf/adrs/adr-004.json +20 -0
- package/rcf/adrs/adr-005.json +20 -0
- package/rcf/adrs/adr-006.json +25 -0
- package/rcf/adrs/adr-007.json +25 -0
- package/rcf/adrs/adr-008.json +25 -0
- package/rcf/adrs/adr-009.json +25 -0
- package/rcf/build-sequence.json +11 -0
- package/rcf/code-nodes/cn-001.json +14 -0
- package/rcf/code-nodes/cn-002.json +14 -0
- package/rcf/code-nodes/cn-003.json +15 -0
- package/rcf/code-nodes/cn-004.json +17 -0
- package/rcf/code-nodes/cn-005.json +19 -0
- package/rcf/code-nodes/cn-006.json +17 -0
- package/rcf/code-nodes/cn-007.json +16 -0
- package/rcf/code-nodes/cn-008.json +19 -0
- package/rcf/code-nodes/cn-009.json +16 -0
- package/rcf/code-nodes/cn-010.json +18 -0
- package/rcf/code-nodes/cn-011.json +18 -0
- package/rcf/code-nodes/cn-012.json +18 -0
- package/rcf/code-nodes/cn-013.json +19 -0
- package/rcf/code-nodes/cn-014.json +16 -0
- package/rcf/code-nodes/cn-015.json +16 -0
- package/rcf/code-nodes/cn-016.json +16 -0
- package/rcf/code-nodes/cn-017.json +16 -0
- package/rcf/code-nodes/cn-018.json +15 -0
- package/rcf/code-nodes/cn-019.json +16 -0
- package/rcf/code-nodes/cn-020.json +16 -0
- package/rcf/code-nodes/cn-021.json +16 -0
- package/rcf/code-nodes/cn-022.json +16 -0
- package/rcf/code-nodes/cn-023.json +16 -0
- package/rcf/code-nodes/cn-024.json +16 -0
- package/rcf/code-nodes/cn-025.json +16 -0
- package/rcf/code-nodes/cn-026.json +16 -0
- package/rcf/code-nodes/cn-027.json +16 -0
- package/rcf/code-nodes/cn-028.json +16 -0
- package/rcf/code-nodes/cn-029.json +19 -0
- package/rcf/code-nodes/cn-030.json +14 -0
- package/rcf/code-nodes/cn-031.json +14 -0
- package/rcf/code-nodes/cn-032.json +14 -0
- package/rcf/code-nodes/cn-033.json +14 -0
- package/rcf/code-nodes/cn-034.json +14 -0
- package/rcf/code-nodes/cn-035.json +14 -0
- package/rcf/code-nodes/cn-036.json +14 -0
- package/rcf/code-nodes/cn-037.json +14 -0
- package/rcf/code-nodes/cn-038.json +14 -0
- package/rcf/code-nodes/cn-039.json +14 -0
- package/rcf/code-nodes/cn-040.json +14 -0
- package/rcf/code-nodes/cn-041.json +14 -0
- package/rcf/code-nodes/cn-042.json +14 -0
- package/rcf/code-nodes/cn-043.json +14 -0
- package/rcf/code-nodes/cn-044.json +14 -0
- package/rcf/code-nodes/cn-045.json +14 -0
- package/rcf/code-nodes/cn-046.json +14 -0
- package/rcf/code-nodes/cn-047.json +14 -0
- package/rcf/code-nodes/cn-048.json +14 -0
- package/rcf/code-nodes/cn-049.json +14 -0
- package/rcf/code-nodes/cn-050.json +14 -0
- package/rcf/code-nodes/cn-051.json +14 -0
- package/rcf/code-nodes/cn-052.json +14 -0
- package/rcf/code-nodes/cn-053.json +14 -0
- package/rcf/code-nodes/cn-054.json +14 -0
- package/rcf/code-nodes/cn-055.json +14 -0
- package/rcf/code-nodes/cn-056.json +14 -0
- package/rcf/code-nodes/cn-057.json +14 -0
- package/rcf/fbs/fbs-001.json +49 -0
- package/rcf/fbs/fbs-002.json +42 -0
- package/rcf/fbs/fbs-003.json +37 -0
- package/rcf/fbs/fbs-004.json +39 -0
- package/rcf/fbs/fbs-005.json +38 -0
- package/rcf/fbs/fbs-006.json +48 -0
- package/rcf/fbs/fbs-007.json +39 -0
- package/rcf/fbs/fbs-008.json +40 -0
- package/rcf/fbs/fbs-009.json +36 -0
- package/rcf/fbs/fbs-010.json +41 -0
- package/rcf/fbs/fbs-011.json +36 -0
- package/rcf/fbs/fbs-012.json +46 -0
- package/rcf/fbs/fbs-013.json +42 -0
- package/rcf/fbs/fbs-014.json +49 -0
- package/rcf/fbs/fbs-015.json +32 -0
- package/rcf/manifest.json +17 -0
- package/rcf/prd.json +47 -0
- package/rcf/requirements/req-001.json +19 -0
- package/rcf/requirements/req-002.json +19 -0
- package/rcf/requirements/req-003.json +19 -0
- package/rcf/requirements/req-004.json +19 -0
- package/rcf/requirements/req-005.json +19 -0
- package/rcf/requirements/req-006.json +19 -0
- package/rcf/requirements/req-007.json +19 -0
- package/rcf/requirements/req-008.json +19 -0
- package/rcf/requirements/req-009.json +19 -0
- package/rcf/tacs/tac-001.json +45 -0
- package/rcf/tacs/tac-002.json +109 -0
- package/rcf/tacs/tac-003.json +40 -0
- package/rcf/tacs/tac-004.json +51 -0
- package/rcf/tacs/tac-005.json +52 -0
- package/rcf/tacs/tac-006.json +104 -0
- package/rcf/tacs/tac-007.json +38 -0
- package/rcf/tacs/tac-008.json +51 -0
- package/rcf/tad.json +51 -0
- package/rcf/test-suites/PENDING.md +23 -0
- package/rcf/test-suites/ts-001.json +38 -0
- package/rcf/test-suites/ts-002.json +38 -0
- package/rcf/test-suites/ts-003.json +43 -0
- package/rcf/test-suites/ts-004.json +44 -0
- package/rcf/test-suites/ts-005.json +30 -0
- package/rcf/test-suites/ts-006.json +36 -0
- package/rcf/test-suites/ts-007.json +43 -0
- package/rcf/test-suites/ts-008.json +37 -0
- package/rcf/test-suites/ts-009.json +38 -0
- package/rcf/test-suites/ts-010.json +38 -0
- package/rcf/test-suites/ts-011.json +44 -0
- package/rcf/test-suites/ts-012.json +36 -0
- package/rcf/test-suites/ts-013.json +38 -0
- package/rcf/test-suites/ts-014.json +38 -0
- package/rcf/test-suites/ts-015.json +38 -0
- package/rcf/test-suites/ts-016.json +37 -0
- package/rcf/test-suites/ts-017.json +38 -0
- package/rcf/test-suites/ts-018.json +38 -0
- package/rcf/test-suites/ts-019.json +37 -0
- package/rcf/test-suites/ts-020.json +46 -0
- package/rcf/test-suites/ts-021.json +46 -0
- package/rcf/test-suites/ts-022.json +46 -0
- package/rcf/test-suites/ts-023.json +46 -0
- package/rcf/test-suites/ts-024.json +46 -0
- package/rcf/test-suites/ts-025.json +52 -0
- package/rcf/user-stories/us-101.json +40 -0
- package/rcf/user-stories/us-102.json +40 -0
- package/rcf/user-stories/us-201.json +40 -0
- package/rcf/user-stories/us-202.json +40 -0
- package/rcf/user-stories/us-203.json +32 -0
- package/rcf/user-stories/us-301.json +40 -0
- package/rcf/user-stories/us-302.json +40 -0
- package/rcf/user-stories/us-303.json +40 -0
- package/rcf/user-stories/us-304.json +40 -0
- package/rcf/user-stories/us-401.json +40 -0
- package/rcf/user-stories/us-402.json +40 -0
- package/rcf/user-stories/us-403.json +40 -0
- package/rcf/user-stories/us-501.json +40 -0
- package/rcf/user-stories/us-502.json +40 -0
- package/rcf/user-stories/us-503.json +40 -0
- package/rcf/user-stories/us-601.json +40 -0
- package/rcf/user-stories/us-602.json +40 -0
- package/rcf/user-stories/us-701.json +40 -0
- package/rcf/user-stories/us-702.json +40 -0
- package/rcf/user-stories/us-801.json +49 -0
- package/rcf/user-stories/us-802.json +49 -0
- package/rcf/user-stories/us-803.json +49 -0
- package/rcf/user-stories/us-804.json +49 -0
- package/rcf/user-stories/us-805.json +49 -0
- package/rcf/user-stories/us-901.json +40 -0
- package/src/.gitkeep +0 -0
- package/src/browser-verify/auth-smoke.js +109 -0
- package/src/browser-verify/index.js +29 -0
- package/src/browser-verify/invariants.js +336 -0
- package/src/browser-verify/manifest-writer.js +189 -0
- package/src/browser-verify/runner.js +171 -0
- package/src/build/bundle.js +198 -0
- package/src/build/formatters/json.js +18 -0
- package/src/build/formatters/markdown.js +406 -0
- package/src/build/index.js +14 -0
- package/src/build/mark.js +177 -0
- package/src/build/queue.js +285 -0
- package/src/cli/browser-verify.js +231 -0
- package/src/cli/build.js +584 -0
- package/src/cli/coverage.js +219 -0
- package/src/cli/create.js +355 -0
- package/src/cli/delete.js +127 -0
- package/src/cli/design.js +353 -0
- package/src/cli/doctor.js +548 -0
- package/src/cli/fbs.js +171 -0
- package/src/cli/finalise.js +377 -0
- package/src/cli/guidance.js +206 -0
- package/src/cli/help.js +156 -0
- package/src/cli/impact.js +119 -0
- package/src/cli/init.js +282 -0
- package/src/cli/intake.js +153 -0
- package/src/cli/link.js +128 -0
- package/src/cli/mcp.js +160 -0
- package/src/cli/preflight.js +220 -0
- package/src/cli/read.js +162 -0
- package/src/cli/req-baseline.js +269 -0
- package/src/cli/req-classify.js +135 -0
- package/src/cli/review.js +295 -0
- package/src/cli/test-suite.js +216 -0
- package/src/cli/trace.js +172 -0
- package/src/cli/ui-baseline.js +292 -0
- package/src/cli/ui-classify.js +108 -0
- package/src/cli/update.js +197 -0
- package/src/cli/validate.js +168 -0
- package/src/cli/view.js +452 -0
- package/src/core/baseline-catalog/data/auth.json +42 -0
- package/src/core/baseline-catalog/data/http-api.json +42 -0
- package/src/core/baseline-catalog/data/notifications.json +33 -0
- package/src/core/baseline-catalog/data/persistence.json +33 -0
- package/src/core/baseline-catalog/data/web-ui.json +60 -0
- package/src/core/baseline-catalog/index.js +121 -0
- package/src/core/errors/index.js +167 -0
- package/src/core/fixtures/register-canary/canary-prompt-01.json +18 -0
- package/src/core/fixtures/register-canary/canary-prompt-02.json +21 -0
- package/src/core/fixtures/register-canary/canary-prompt-03.json +17 -0
- package/src/core/isolation/index.js +60 -0
- package/src/core/mcp/framing.js +103 -0
- package/src/core/mcp/index.js +8 -0
- package/src/core/mcp/server.js +228 -0
- package/src/core/patterns/register-canary.js +209 -0
- package/src/core/patterns/req-shapes.js +158 -0
- package/src/core/patterns/services.js +358 -0
- package/src/core/patterns/ui-shapes.js +166 -0
- package/src/core/store/cn-resolve.js +134 -0
- package/src/core/store/derive-deps.js +93 -0
- package/src/core/store/ids.js +78 -0
- package/src/core/store/index.js +20 -0
- package/src/core/store/init.js +255 -0
- package/src/core/store/loader.js +211 -0
- package/src/core/store/tp-resolve.js +176 -0
- package/src/core/store/validator.js +191 -0
- package/src/core/store/walker.js +898 -0
- package/src/core/store/writer.js +1849 -0
- package/src/design/index.js +11 -0
- package/src/design/writer.js +271 -0
- package/src/finalise/detect.js +129 -0
- package/src/finalise/index.js +17 -0
- package/src/finalise/ingest.js +119 -0
- package/src/finalise/install.js +119 -0
- package/src/finalise/ship-without-verified.js +131 -0
- package/src/finalise/spawn.js +84 -0
- package/src/intake/fidelity.js +105 -0
- package/src/intake/index.js +6 -0
- package/src/intake/manifest-writer.js +100 -0
- package/src/intake/orchestrator.js +138 -0
- package/src/intake/validate.js +80 -0
- package/src/mcp/map-errors.js +131 -0
- package/src/mcp/prompts.js +49 -0
- package/src/mcp/resources.js +244 -0
- package/src/mcp/tools.js +1204 -0
- package/src/preflight/design-shapes.js +185 -0
- package/src/preflight/index.js +90 -0
- package/src/preflight/manifest-writer.js +264 -0
- package/src/preflight/scanner.js +206 -0
- package/src/preflight/secrets.js +134 -0
- package/src/preflight/session.js +246 -0
- package/src/query/attestation.js +285 -0
- package/src/query/coverage.js +308 -0
- package/src/query/formatters/json.js +21 -0
- package/src/query/formatters/mermaid.js +209 -0
- package/src/query/formatters/table.js +203 -0
- package/src/query/impact.js +173 -0
- package/src/query/index.js +9 -0
- package/src/query/trace.js +345 -0
- package/src/register-canary/fixture-loader.js +87 -0
- package/src/register-canary/index.js +10 -0
- package/src/register-canary/record-writer.js +132 -0
- package/src/register-canary/runner.js +156 -0
- package/src/req-baseline/gate.js +86 -0
- package/src/req-baseline/index.js +27 -0
- package/src/req-baseline/open-candidates.js +143 -0
- package/src/req-baseline/opt-out.js +195 -0
- package/src/req-baseline/sweep.js +230 -0
- package/src/req-detection/classifier.js +181 -0
- package/src/req-detection/index.js +9 -0
- package/src/req-detection/persist.js +55 -0
- package/src/review/index.js +325 -0
- package/src/review/mutation.js +117 -0
- package/src/review/ui-baseline-drift.js +138 -0
- package/src/server/index.js +178 -0
- package/src/server/routes.js +110 -0
- package/src/server/sse.js +118 -0
- package/src/setup/agent-setup.js +362 -0
- package/src/setup/identity-seed.js +104 -0
- package/src/setup/knowledge-seed.js +123 -0
- package/src/setup/managed-block.js +193 -0
- package/src/setup/managed-gitignore.js +166 -0
- package/src/setup/managed-markers.js +49 -0
- package/src/ui-baseline/defaults.js +119 -0
- package/src/ui-baseline/index.js +25 -0
- package/src/ui-baseline/manifest-writer.js +282 -0
- package/src/ui-baseline/session.js +178 -0
- package/src/ui-detection/classifier.js +192 -0
- package/src/verify/chain/index.js +190 -0
- package/src/verify/cli/cleanup.js +61 -0
- package/src/verify/cli/help.js +56 -0
- package/src/verify/cli/mcp.js +98 -0
- package/src/verify/cli/provision.js +71 -0
- package/src/verify/cli/report.js +71 -0
- package/src/verify/cli/run.js +155 -0
- package/src/verify/engine/brief.js +87 -0
- package/src/verify/engine/index.js +177 -0
- package/src/verify/engine/launcher.js +307 -0
- package/src/verify/mcp/tools.js +107 -0
- package/src/verify/profile/index.js +146 -0
- package/src/verify/provision/index.js +256 -0
- package/src/verify/report/index.js +139 -0
- package/src/verify/report/renderer.js +118 -0
- package/src/verify/verdict/index.js +246 -0
- package/src/view/doc-renderers/adr.js +44 -0
- package/src/view/doc-renderers/build-sequence.js +40 -0
- package/src/view/doc-renderers/fbs.js +128 -0
- package/src/view/doc-renderers/helpers.js +159 -0
- package/src/view/doc-renderers/index.js +12 -0
- package/src/view/doc-renderers/prd.js +45 -0
- package/src/view/doc-renderers/req.js +43 -0
- package/src/view/doc-renderers/tac.js +38 -0
- package/src/view/doc-renderers/tad.js +74 -0
- package/src/view/doc-renderers/test-suite.js +45 -0
- package/src/view/doc-renderers/user-story.js +63 -0
- package/src/view/html-page.js +462 -0
- package/src/view/index.js +63 -0
- package/src/view/live-client.js +338 -0
- package/src/view/mermaid-diagram.js +178 -0
- package/src/view/style.css +735 -0
- package/src/view/tree-model.js +152 -0
- package/src/view/vendored/mermaid.min.js +2607 -0
- package/src/view-supervisor/index.js +26 -0
- package/src/view-supervisor/logs.js +32 -0
- package/src/view-supervisor/manifest-writer.js +178 -0
- package/src/view-supervisor/persist-until.js +85 -0
- package/src/view-supervisor/supervisor.js +276 -0
- package/src/watch/index.js +152 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "US-503",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "REQ-005",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"status": "draft",
|
|
7
|
+
"title": "Mark a slice done",
|
|
8
|
+
"description": "A project owner or AI tool marks an FBS slice done so the Build Sequence reflects real progress and coverage stays honest.",
|
|
9
|
+
"asA": "project owner or AI tool",
|
|
10
|
+
"iWant": "to mark a build slice done once it is finished",
|
|
11
|
+
"soThat": "the build sequence reflects real progress and the coverage report stays honest",
|
|
12
|
+
"acceptanceCriteria": [
|
|
13
|
+
{
|
|
14
|
+
"id": "AC-503-1",
|
|
15
|
+
"description": "Marking done advances the FBS execution status and the matching Build Sequence slot status, both validating",
|
|
16
|
+
"given": "a finished slice",
|
|
17
|
+
"when": "it is marked done",
|
|
18
|
+
"then": "the FBS execution status advances and the corresponding Build Sequence slot status is updated, both validating",
|
|
19
|
+
"testable": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-503-2",
|
|
23
|
+
"description": "Mark-done on an unknown FBS id returns a not-found error and writes nothing",
|
|
24
|
+
"given": "a mark-done request for an unknown FBS id",
|
|
25
|
+
"when": "it runs",
|
|
26
|
+
"then": "a not-found error is returned and nothing is written",
|
|
27
|
+
"testable": true
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "AC-503-3",
|
|
31
|
+
"description": "Mark-done only changes execution status fields and leaves the rest of the documents untouched",
|
|
32
|
+
"given": "a mark-done operation",
|
|
33
|
+
"when": "it runs",
|
|
34
|
+
"then": "it changes only execution status fields and leaves the rest of the documents untouched",
|
|
35
|
+
"testable": true
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"createdAt": "2026-06-25T00:00:00Z",
|
|
39
|
+
"updatedAt": "2026-06-25T00:00:00Z"
|
|
40
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "US-601",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "REQ-006",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"status": "draft",
|
|
7
|
+
"title": "Query and view over MCP",
|
|
8
|
+
"description": "An AI tool running in a harness uses the local stdio MCP server to query and view the project's RCF tree without shelling out to the CLI.",
|
|
9
|
+
"asA": "AI tool running in a harness",
|
|
10
|
+
"iWant": "the query and view operations exposed as MCP tools over local stdio",
|
|
11
|
+
"soThat": "I can read and report on the project's RCF tree without shelling out to the CLI",
|
|
12
|
+
"acceptanceCriteria": [
|
|
13
|
+
{
|
|
14
|
+
"id": "AC-601-1",
|
|
15
|
+
"description": "An MCP client listing tools sees the query and view operations with structured input and output",
|
|
16
|
+
"given": "a running local stdio MCP server",
|
|
17
|
+
"when": "an MCP client lists tools",
|
|
18
|
+
"then": "the query and view operations are present with structured input and output",
|
|
19
|
+
"testable": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-601-2",
|
|
23
|
+
"description": "A coverage query over MCP returns the same result the CLI coverage command returns for the same project",
|
|
24
|
+
"given": "a coverage query over MCP",
|
|
25
|
+
"when": "it runs",
|
|
26
|
+
"then": "it returns the same result the CLI coverage command returns for the same project",
|
|
27
|
+
"testable": true
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "AC-601-3",
|
|
31
|
+
"description": "The MCP server communicates over local stdio only and opens no network listener",
|
|
32
|
+
"given": "the MCP server",
|
|
33
|
+
"when": "it runs",
|
|
34
|
+
"then": "it communicates over local stdio only and opens no network listener",
|
|
35
|
+
"testable": true
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"createdAt": "2026-06-25T00:00:00Z",
|
|
39
|
+
"updatedAt": "2026-06-25T00:00:00Z"
|
|
40
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "US-602",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "REQ-006",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"status": "draft",
|
|
7
|
+
"title": "CRUD and build over MCP",
|
|
8
|
+
"description": "An AI tool running in a harness uses MCP tools to mutate the RCF tree and assemble build prompts with the same validation behaviour as the CLI.",
|
|
9
|
+
"asA": "AI tool running in a harness",
|
|
10
|
+
"iWant": "the CRUD and build operations exposed as MCP tools",
|
|
11
|
+
"soThat": "I can construct and maintain the RCF tree on the owner's behalf through structured tools that validate",
|
|
12
|
+
"acceptanceCriteria": [
|
|
13
|
+
{
|
|
14
|
+
"id": "AC-602-1",
|
|
15
|
+
"description": "A create operation over MCP applies the same validation and parent-linkage behaviour as the CLI create verb",
|
|
16
|
+
"given": "a create operation over MCP",
|
|
17
|
+
"when": "it runs",
|
|
18
|
+
"then": "it applies the same validation and parent-linkage behaviour as the CLI create verb",
|
|
19
|
+
"testable": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-602-2",
|
|
23
|
+
"description": "A build-assembly operation over MCP returns the assembled prompt for the named FBS",
|
|
24
|
+
"given": "a build-assembly operation over MCP",
|
|
25
|
+
"when": "it runs",
|
|
26
|
+
"then": "it returns the assembled prompt for the named FBS",
|
|
27
|
+
"testable": true
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "AC-602-3",
|
|
31
|
+
"description": "A mutating MCP operation that would write an invalid document writes nothing and returns the validation error",
|
|
32
|
+
"given": "any mutating MCP operation that would write an invalid document",
|
|
33
|
+
"when": "it runs",
|
|
34
|
+
"then": "nothing is written and the validation error is returned to the client",
|
|
35
|
+
"testable": true
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"createdAt": "2026-06-25T00:00:00Z",
|
|
39
|
+
"updatedAt": "2026-06-25T00:00:00Z"
|
|
40
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "US-701",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "REQ-007",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"status": "draft",
|
|
7
|
+
"title": "Refuse invalid writes",
|
|
8
|
+
"description": "A project owner trusts that the tool refuses to write any document that does not validate, so on-disk state is always valid even when the owner cannot inspect it.",
|
|
9
|
+
"asA": "project owner",
|
|
10
|
+
"iWant": "the tool to refuse to write any document that does not validate against the schema",
|
|
11
|
+
"soThat": "what is on disk is always valid, even though I cannot check it myself",
|
|
12
|
+
"acceptanceCriteria": [
|
|
13
|
+
{
|
|
14
|
+
"id": "AC-701-1",
|
|
15
|
+
"description": "A create or update that would produce an invalid document writes nothing",
|
|
16
|
+
"given": "any create or update that would produce an invalid document",
|
|
17
|
+
"when": "it runs",
|
|
18
|
+
"then": "nothing is written",
|
|
19
|
+
"testable": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-701-2",
|
|
23
|
+
"description": "A successful write produces a document that validates against its schema",
|
|
24
|
+
"given": "a successful write",
|
|
25
|
+
"when": "it completes",
|
|
26
|
+
"then": "the written document validates against its schema",
|
|
27
|
+
"testable": true
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "AC-701-3",
|
|
31
|
+
"description": "Validation uses the published schema bundle registered once at start-up, not a local copy",
|
|
32
|
+
"given": "the validation step",
|
|
33
|
+
"when": "it runs",
|
|
34
|
+
"then": "it uses the published schema bundle registered once at start-up, not a local copy that could drift",
|
|
35
|
+
"testable": true
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"createdAt": "2026-06-25T00:00:00Z",
|
|
39
|
+
"updatedAt": "2026-06-25T00:00:00Z"
|
|
40
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "US-702",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "REQ-007",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"status": "draft",
|
|
7
|
+
"title": "Clear validation errors",
|
|
8
|
+
"description": "A project owner or AI tool gets structured, readable validation errors that name the offending field and rule, with all failures in one document reported together.",
|
|
9
|
+
"asA": "project owner or AI tool",
|
|
10
|
+
"iWant": "validation failures reported as clear, structured errors",
|
|
11
|
+
"soThat": "I can understand and fix what is wrong without reading the schema",
|
|
12
|
+
"acceptanceCriteria": [
|
|
13
|
+
{
|
|
14
|
+
"id": "AC-702-1",
|
|
15
|
+
"description": "A reported validation failure names the offending field and the rule it broke",
|
|
16
|
+
"given": "a validation failure",
|
|
17
|
+
"when": "it is reported",
|
|
18
|
+
"then": "the error names the offending field and the rule it broke",
|
|
19
|
+
"testable": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-702-2",
|
|
23
|
+
"description": "Multiple validation failures in one document are returned together, not just the first",
|
|
24
|
+
"given": "multiple validation failures in one document",
|
|
25
|
+
"when": "they are reported",
|
|
26
|
+
"then": "all of them are returned together, not just the first",
|
|
27
|
+
"testable": true
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "AC-702-3",
|
|
31
|
+
"description": "Validation errors delivered to an AI tool over MCP are structured objects the tool can act on, not free text",
|
|
32
|
+
"given": "a validation error returned to an AI tool over MCP",
|
|
33
|
+
"when": "it is delivered",
|
|
34
|
+
"then": "it is a structured object the tool can act on, not a free-text string",
|
|
35
|
+
"testable": true
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"createdAt": "2026-06-25T00:00:00Z",
|
|
39
|
+
"updatedAt": "2026-06-25T00:00:00Z"
|
|
40
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-07-20T17:03:40.038Z",
|
|
3
|
+
"updatedAt": "2026-07-20T17:10:45.603Z",
|
|
4
|
+
"description": "The build loop leaves every project with a working, documented local preview as its default outcome, so a non-coding owner always has a runtime they can drive and review without a cloud account or a deploy step.",
|
|
5
|
+
"asA": "non-coding product owner",
|
|
6
|
+
"iWant": "every build to leave me a working, documented way to run the app locally",
|
|
7
|
+
"soThat": "I can see and use what was built without needing to deploy it anywhere first",
|
|
8
|
+
"usId": "US-801",
|
|
9
|
+
"prdId": "PRD-001",
|
|
10
|
+
"reqId": "REQ-008",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"title": "Every build leaves a working local preview",
|
|
14
|
+
"acceptanceCriteria": [
|
|
15
|
+
{
|
|
16
|
+
"id": "AC-801-1",
|
|
17
|
+
"description": "A build's definition of done requires a documented local preview loop as the default outcome",
|
|
18
|
+
"given": "the RCF build method as taught by the shipped guidance pack",
|
|
19
|
+
"when": "a build reaches its definition of done",
|
|
20
|
+
"then": "the guidance requires a working, documented local preview loop (a dev server, and seeded data where the app needs it) to be present as the default deliverable",
|
|
21
|
+
"testable": true
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "AC-801-2",
|
|
25
|
+
"description": "The local preview is startable via a single documented command where the stack allows",
|
|
26
|
+
"given": "the shipped build guidance describing the local preview",
|
|
27
|
+
"when": "it states how the owner starts the app",
|
|
28
|
+
"then": "it directs the build toward one documented command to start the preview wherever the stack makes a single command possible",
|
|
29
|
+
"testable": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "AC-801-3",
|
|
33
|
+
"description": "The local preview is produced whether or not a hosting target was stated",
|
|
34
|
+
"given": "an owner who has not stated a hosting target, or who asked for a recommendation instead",
|
|
35
|
+
"when": "the build completes",
|
|
36
|
+
"then": "the guidance still requires the local preview to be produced as the default, not made conditional on a stated host",
|
|
37
|
+
"testable": true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "AC-801-4",
|
|
41
|
+
"description": "The preview includes seeded data when the app needs data to be usable",
|
|
42
|
+
"given": "an application that needs data present to be exercisable",
|
|
43
|
+
"when": "the local preview loop is produced",
|
|
44
|
+
"then": "the guidance requires seeded or sample data so the preview can actually be driven, not an empty shell",
|
|
45
|
+
"testable": true
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"tacIds": []
|
|
49
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-07-20T17:04:24.408Z",
|
|
3
|
+
"updatedAt": "2026-07-20T17:10:45.759Z",
|
|
4
|
+
"description": "Elicitation establishes where the application will run before any stack is committed, and the stack the tool builds is constrained by that answer, so the owner is not led into a stack their hosting cannot run.",
|
|
5
|
+
"asA": "non-coding product owner",
|
|
6
|
+
"iWant": "the tool to work out where my app will run before it picks the technology to build it with",
|
|
7
|
+
"soThat": "it does not build me something my hosting cannot actually run",
|
|
8
|
+
"usId": "US-802",
|
|
9
|
+
"prdId": "PRD-001",
|
|
10
|
+
"reqId": "REQ-008",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"title": "Deploy target is established before the stack is chosen",
|
|
14
|
+
"acceptanceCriteria": [
|
|
15
|
+
{
|
|
16
|
+
"id": "AC-802-1",
|
|
17
|
+
"description": "Elicitation asks where the app will run as an early item before any stack is committed",
|
|
18
|
+
"given": "the shipped elicitation guidance",
|
|
19
|
+
"when": "an agent runs elicitation with an owner",
|
|
20
|
+
"then": "the guidance places a deploy-target question early, before any technology stack is committed",
|
|
21
|
+
"testable": true
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "AC-802-2",
|
|
25
|
+
"description": "The stack choice is constrained by the deploy-target answer",
|
|
26
|
+
"given": "a stated deploy target",
|
|
27
|
+
"when": "the agent chooses the technology stack",
|
|
28
|
+
"then": "the guidance requires the stack to be constrained to what that target can host, so an incompatible stack is not committed",
|
|
29
|
+
"testable": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "AC-802-3",
|
|
33
|
+
"description": "The deploy target and its stack implication are captured as an ADR on the project tree",
|
|
34
|
+
"given": "a deploy target established during elicitation",
|
|
35
|
+
"when": "the decision is made",
|
|
36
|
+
"then": "the guidance requires it and the stack constraint it implies to be recorded as an ADR on the project's own tree, visible and revisable",
|
|
37
|
+
"testable": true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "AC-802-4",
|
|
41
|
+
"description": "The harness fragment forbids committing a stack before the deploy target is established",
|
|
42
|
+
"given": "the harness fragment written into agent-instructions files",
|
|
43
|
+
"when": "it is inspected",
|
|
44
|
+
"then": "it carries a rule that a technology stack must not be committed before the deploy target is established",
|
|
45
|
+
"testable": true
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"tacIds": []
|
|
49
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-07-20T17:04:24.594Z",
|
|
3
|
+
"updatedAt": "2026-07-20T17:10:45.914Z",
|
|
4
|
+
"description": "When the owner does not know where the application will run, the agent walks them through choosing and configuring a hosting account in plain language, honestly isolating the steps only the human account-holder can do, rather than choosing silently or pretending to act as them.",
|
|
5
|
+
"asA": "non-coding product owner who does not know my hosting options",
|
|
6
|
+
"iWant": "to be walked through choosing and setting up somewhere to run my app, in plain language",
|
|
7
|
+
"soThat": "I can make and act on the hosting decision without already being an expert",
|
|
8
|
+
"usId": "US-803",
|
|
9
|
+
"prdId": "PRD-001",
|
|
10
|
+
"reqId": "REQ-008",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"title": "Hosting-choice guidance when the owner is unsure",
|
|
14
|
+
"acceptanceCriteria": [
|
|
15
|
+
{
|
|
16
|
+
"id": "AC-803-1",
|
|
17
|
+
"description": "When the owner does not know where the app will run, the agent runs a hosting-choice walkthrough rather than choosing silently",
|
|
18
|
+
"given": "an owner who does not know their hosting options",
|
|
19
|
+
"when": "the deploy-target question is reached",
|
|
20
|
+
"then": "the guidance directs the agent to run a hosting-choice walkthrough instead of silently selecting a host",
|
|
21
|
+
"testable": true
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "AC-803-2",
|
|
25
|
+
"description": "The walkthrough explains the options in plain language",
|
|
26
|
+
"given": "the hosting-choice walkthrough guidance",
|
|
27
|
+
"when": "it presents hosting options to the owner",
|
|
28
|
+
"then": "it requires plain-language explanation with no unexplained jargon",
|
|
29
|
+
"testable": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "AC-803-3",
|
|
33
|
+
"description": "Steps only the human account-holder can do are isolated and named honestly",
|
|
34
|
+
"given": "the walkthrough reaching steps only the account-holder can perform (sign-ups, billing, tokens, CLI authentication)",
|
|
35
|
+
"when": "those steps arise",
|
|
36
|
+
"then": "the guidance requires them to be isolated and named honestly as the human's to do, not performed silently by the agent nor pretended",
|
|
37
|
+
"testable": true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "AC-803-4",
|
|
41
|
+
"description": "The walkthrough covers configuring the chosen account, not only naming a provider",
|
|
42
|
+
"given": "a hosting choice the owner has made",
|
|
43
|
+
"when": "the walkthrough continues past the choice",
|
|
44
|
+
"then": "the guidance requires it to cover configuring the account - accounts, tokens and CLI setup - not just naming a provider",
|
|
45
|
+
"testable": true
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"tacIds": []
|
|
49
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-07-20T17:04:24.748Z",
|
|
3
|
+
"updatedAt": "2026-07-20T17:10:46.062Z",
|
|
4
|
+
"description": "Every claim the tool or its agent makes that something is verified or tested names the runtime it was checked against, and never implies verification on a deployed runtime that did not happen, so the owner can tell what was actually proven.",
|
|
5
|
+
"asA": "non-coding product owner",
|
|
6
|
+
"iWant": "every claim that something was verified to say what it was verified against",
|
|
7
|
+
"soThat": "I am not told the deployed app works when only a local emulator was checked",
|
|
8
|
+
"usId": "US-804",
|
|
9
|
+
"prdId": "PRD-001",
|
|
10
|
+
"reqId": "REQ-008",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"title": "Verification claims name their runtime",
|
|
14
|
+
"acceptanceCriteria": [
|
|
15
|
+
{
|
|
16
|
+
"id": "AC-804-1",
|
|
17
|
+
"description": "Every verified or tested claim names the runtime it was checked against",
|
|
18
|
+
"given": "the shipped build guidance on reporting verification",
|
|
19
|
+
"when": "a 'verified' or 'tested' claim is made",
|
|
20
|
+
"then": "the guidance requires the claim to name the runtime it was checked against",
|
|
21
|
+
"testable": true
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "AC-804-2",
|
|
25
|
+
"description": "No claim implies deploy-runtime verification that did not happen",
|
|
26
|
+
"given": "a verification that ran against a local or emulated runtime",
|
|
27
|
+
"when": "the claim is written",
|
|
28
|
+
"then": "the guidance forbids the claim from stating or implying verification on a deployed runtime that was not exercised",
|
|
29
|
+
"testable": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "AC-804-3",
|
|
33
|
+
"description": "The PR-authoring guidance requires the runtime label in the verification section",
|
|
34
|
+
"given": "the build-cycle PR-authoring guidance",
|
|
35
|
+
"when": "the verification section of a PR body is authored",
|
|
36
|
+
"then": "it requires each verification claim to carry the runtime it was checked against",
|
|
37
|
+
"testable": true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "AC-804-4",
|
|
41
|
+
"description": "The guidance includes an explicit labelled-claim example",
|
|
42
|
+
"given": "the shipped build guidance",
|
|
43
|
+
"when": "it illustrates a verification claim",
|
|
44
|
+
"then": "it includes an explicit example naming the runtime (for example 'verified against wrangler dev (localhost) - NOT the deployed Worker runtime')",
|
|
45
|
+
"testable": true
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"tacIds": []
|
|
49
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-07-20T17:04:24.904Z",
|
|
3
|
+
"updatedAt": "2026-07-28T16:39:51.461Z",
|
|
4
|
+
"description": "The method carries guidance for a periodic and end-of-build fresh-context self-review that drives the app against its acceptance criteria to catch the defect classes green test suites miss, honestly scoped as an in-loop check subordinate to the independent verification gate that rcf finalise runs.",
|
|
5
|
+
"asA": "non-coding product owner",
|
|
6
|
+
"iWant": "the build to include a periodic fresh look that actually drives the app against what it is supposed to do",
|
|
7
|
+
"soThat": "defects my passing tests miss are caught before I rely on the result",
|
|
8
|
+
"usId": "US-805",
|
|
9
|
+
"prdId": "PRD-001",
|
|
10
|
+
"reqId": "REQ-008",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"title": "Interim self-review guidance",
|
|
14
|
+
"acceptanceCriteria": [
|
|
15
|
+
{
|
|
16
|
+
"id": "AC-805-1",
|
|
17
|
+
"description": "The guidance describes a periodic and end-of-build fresh-context self-review dispatch",
|
|
18
|
+
"given": "the shipped build guidance",
|
|
19
|
+
"when": "it describes the self-review",
|
|
20
|
+
"then": "it describes a fresh-context manual-review subagent dispatch run periodically (every few FBS builds) and once at the end of the build",
|
|
21
|
+
"testable": true
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "AC-805-2",
|
|
25
|
+
"description": "The reviewer drives the app against the acceptance criteria rather than reading the code",
|
|
26
|
+
"given": "the self-review guidance",
|
|
27
|
+
"when": "it states what the reviewer does",
|
|
28
|
+
"then": "it requires the reviewer to drive the running application against its acceptance criteria, not to read the code",
|
|
29
|
+
"testable": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "AC-805-3",
|
|
33
|
+
"description": "The review targets the named defect classes",
|
|
34
|
+
"given": "the self-review guidance",
|
|
35
|
+
"when": "it states what the review looks for",
|
|
36
|
+
"then": "it names the target defect classes: session-class bugs, false-promise UI, runtime mismatch (localhost versus deployed), dead auth paths and dead code",
|
|
37
|
+
"testable": true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "AC-805-4",
|
|
41
|
+
"description": "The guidance scopes the self-review honestly as an in-loop check and not the independent gate",
|
|
42
|
+
"given": "the self-review guidance",
|
|
43
|
+
"when": "it frames the review",
|
|
44
|
+
"then": "it states plainly that this is an in-loop check and not the independent verification gate, names rcf finalise (section 7) as the gate, and says it is guidance and not a new subsystem",
|
|
45
|
+
"testable": true
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"tacIds": []
|
|
49
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "US-901",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "REQ-009",
|
|
5
|
+
"title": "Route `rcf verify` through the same dispatcher as the alias bin",
|
|
6
|
+
"description": "A consumer running the unified `rcf` CLI can reach the adversarial ship-gate verifier as `rcf verify <verb>` and get identical behaviour to the legacy `rcf-verify <verb>` invocation. The legacy bin remains available and emits a one-line deprecation notice on stderr so scripts can be migrated at their own pace.",
|
|
7
|
+
"asA": "consumer of the RCF Lite CLI",
|
|
8
|
+
"iWant": "to invoke the verify suite as `rcf verify <verb>` inside the unified CLI",
|
|
9
|
+
"soThat": "verify sits inside the same verb space as the rest of the RCF chain and I only have to install one package",
|
|
10
|
+
"acceptanceCriteria": [
|
|
11
|
+
{
|
|
12
|
+
"id": "AC-901-1",
|
|
13
|
+
"description": "The `rcf` bin exposes `verify` as a top-level subcommand routed to the same dispatcher as the `rcf-verify` alias bin",
|
|
14
|
+
"given": "the unified `rcf` binary imported from bin/rcf.js",
|
|
15
|
+
"when": "`verify` is looked up on the top-level SUBCOMMANDS map",
|
|
16
|
+
"then": "the handler resolves to the same `main` function that bin/rcf-verify.js exports and dispatches over run/report/provision/cleanup/mcp/help",
|
|
17
|
+
"testable": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "AC-901-2",
|
|
21
|
+
"description": "The top-level `rcf --help` output advertises `verify` as an available subcommand",
|
|
22
|
+
"given": "the unified `rcf` binary",
|
|
23
|
+
"when": "`--help` or `help` runs",
|
|
24
|
+
"then": "the printed usage lists `verify <verb>` alongside the other top-level commands",
|
|
25
|
+
"testable": true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "AC-901-3",
|
|
29
|
+
"description": "The `rcf-verify` alias bin emits a one-line stderr deprecation notice when invoked directly and stays fully functional",
|
|
30
|
+
"given": "the `rcf-verify` alias bin invoked as the entry point (isMain)",
|
|
31
|
+
"when": "the entry point runs without RCF_QUIET",
|
|
32
|
+
"then": "a single line describing the deprecation and the `rcf verify` replacement is written to stderr before dispatch, and the dispatch itself is unchanged",
|
|
33
|
+
"testable": true
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"version": "0.1.0",
|
|
37
|
+
"status": "draft",
|
|
38
|
+
"createdAt": "2026-08-11T00:00:00Z",
|
|
39
|
+
"updatedAt": "2026-08-11T00:00:00Z"
|
|
40
|
+
}
|
package/src/.gitkeep
ADDED
|
File without changes
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Auth-REQ smoke checks (ui-design-gate-0.7.0-spec §9).
|
|
2
|
+
//
|
|
3
|
+
// A small pack of curl-shape checks that run at Finalise for any FBS
|
|
4
|
+
// binding an auth REQ. Composes with Track A's preflight rec 3
|
|
5
|
+
// (`uiBaseline.defaults.authFlow.htmlLoginPageRequired`); when the
|
|
6
|
+
// baseline says API-only, the pack is skipped.
|
|
7
|
+
//
|
|
8
|
+
// Directly addresses the cold-run defect where `/login` returned 404
|
|
9
|
+
// for the full run. Implemented as fetch-shaped checks against a
|
|
10
|
+
// runtime URL; the runner (injectable) is the ambient `fetch` by
|
|
11
|
+
// default. Callers pass `runtimeUrl` (e.g. http://127.0.0.1:3000).
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {object} AuthSmokeResult
|
|
15
|
+
* @property {string} check
|
|
16
|
+
* @property {number} [status]
|
|
17
|
+
* @property {string} [contentType]
|
|
18
|
+
* @property {'pass'|'warn'|'fail'} verdict
|
|
19
|
+
* @property {string} [detail]
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {object} AuthSmokeRunnerInput
|
|
24
|
+
* @property {(url: string, init?: object) => Promise<{ status: number, headers: { get: (name: string) => string|null } }>} fetch
|
|
25
|
+
* @property {string} runtimeUrl
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const HTML_CONTENT_TYPE_RE = /^text\/html\b/i;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* True when a FBS should run the auth smoke pack. Reads (in priority
|
|
32
|
+
* order) the FBS's own dependsOnServices auth categories, then falls
|
|
33
|
+
* back to the manifest's uiBaseline.defaults.authFlow.smokeChecksRequired.
|
|
34
|
+
*
|
|
35
|
+
* @param {object} fbs
|
|
36
|
+
* @param {object|null} uiBaseline
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
export function shouldRunAuthSmokeChecks(fbs, uiBaseline) {
|
|
40
|
+
const services = Array.isArray(fbs?.dependsOnServices) ? fbs.dependsOnServices : [];
|
|
41
|
+
const authCategories = new Set(['auth', 'oauth', 'identityProvider', 'emailAuth']);
|
|
42
|
+
const bindsAuth = services.some((s) => authCategories.has(String(s?.serviceCategory ?? '')));
|
|
43
|
+
const baselineRequires = uiBaseline?.defaults?.authFlow?.htmlLoginPageRequired === true
|
|
44
|
+
&& uiBaseline?.defaults?.authFlow?.smokeChecksRequired !== false;
|
|
45
|
+
return bindsAuth || baselineRequires;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Run the smoke pack against `runtimeUrl`. Returns one result per check.
|
|
50
|
+
*
|
|
51
|
+
* @param {AuthSmokeRunnerInput} args
|
|
52
|
+
* @returns {Promise<AuthSmokeResult[]>}
|
|
53
|
+
*/
|
|
54
|
+
export async function runAuthSmokeChecks({ fetch, runtimeUrl }) {
|
|
55
|
+
/** @type {AuthSmokeResult[]} */
|
|
56
|
+
const results = [];
|
|
57
|
+
results.push(await runOne({
|
|
58
|
+
check: 'GET /login', fetch,
|
|
59
|
+
request: () => fetch(joinUrl(runtimeUrl, '/login')),
|
|
60
|
+
accept: (status, contentType) => {
|
|
61
|
+
if (status !== 200) return { verdict: 'fail', detail: `status ${status} (expected 200)` };
|
|
62
|
+
if (!HTML_CONTENT_TYPE_RE.test(contentType ?? '')) return { verdict: 'fail', detail: `content-type '${contentType ?? '(missing)'}' (expected text/html)` };
|
|
63
|
+
return { verdict: 'pass' };
|
|
64
|
+
},
|
|
65
|
+
}));
|
|
66
|
+
results.push(await runOne({
|
|
67
|
+
check: 'POST /logout', fetch,
|
|
68
|
+
request: () => fetch(joinUrl(runtimeUrl, '/logout'), { method: 'POST', redirect: 'manual' }),
|
|
69
|
+
accept: (status) => {
|
|
70
|
+
if (status === 200 || status === 302 || status === 303) return { verdict: 'pass' };
|
|
71
|
+
return { verdict: 'fail', detail: `status ${status} (expected 200 | 302 | 303)` };
|
|
72
|
+
},
|
|
73
|
+
}));
|
|
74
|
+
results.push(await runOne({
|
|
75
|
+
check: 'GET /login/verify?token=',
|
|
76
|
+
fetch,
|
|
77
|
+
request: () => fetch(joinUrl(runtimeUrl, '/login/verify?token='), { redirect: 'manual' }),
|
|
78
|
+
accept: (status) => {
|
|
79
|
+
if (status === 400 || status === 401 || status === 403) return { verdict: 'pass' };
|
|
80
|
+
if (status === 302 || status === 303) return { verdict: 'pass' };
|
|
81
|
+
if (status === 200) return { verdict: 'fail', detail: 'status 200 (empty-token accepted; regression on the empty-token vuln)' };
|
|
82
|
+
return { verdict: 'fail', detail: `status ${status} (expected 400 | 401 | 403 | 302 | 303)` };
|
|
83
|
+
},
|
|
84
|
+
}));
|
|
85
|
+
return results;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function runOne({ check, request, accept }) {
|
|
89
|
+
try {
|
|
90
|
+
const response = await request();
|
|
91
|
+
const status = response?.status;
|
|
92
|
+
const contentType = response?.headers?.get ? response.headers.get('content-type') : null;
|
|
93
|
+
const outcome = accept(status, contentType);
|
|
94
|
+
return {
|
|
95
|
+
check,
|
|
96
|
+
status,
|
|
97
|
+
...(contentType ? { contentType } : {}),
|
|
98
|
+
verdict: outcome.verdict,
|
|
99
|
+
...(outcome.detail ? { detail: outcome.detail } : {}),
|
|
100
|
+
};
|
|
101
|
+
} catch (err) {
|
|
102
|
+
return { check, verdict: 'fail', detail: `request failed: ${err.message}` };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function joinUrl(base, path) {
|
|
107
|
+
const trimmed = base.replace(/\/+$/, '');
|
|
108
|
+
return `${trimmed}${path.startsWith('/') ? path : `/${path}`}`;
|
|
109
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Public surface for the browser-verify module
|
|
2
|
+
// (ui-design-gate-0.7.0-spec §8, §9). CLI handler at
|
|
3
|
+
// `src/cli/browser-verify.js`.
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
UI_INVARIANTS_V1,
|
|
7
|
+
compareTopLevelStructure,
|
|
8
|
+
foldInvariantsForRecord,
|
|
9
|
+
runInvariantsForCapture,
|
|
10
|
+
} from './invariants.js';
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
runAuthSmokeChecks,
|
|
14
|
+
shouldRunAuthSmokeChecks,
|
|
15
|
+
} from './auth-smoke.js';
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
aggregateVerdict,
|
|
19
|
+
composeBrowserVerificationRecord,
|
|
20
|
+
nextBrowserVerificationId,
|
|
21
|
+
writeBrowserVerificationAck,
|
|
22
|
+
writeBrowserVerificationRecord,
|
|
23
|
+
} from './manifest-writer.js';
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
composeOperatorSessionRecord,
|
|
27
|
+
runAgentScreenshotCritique,
|
|
28
|
+
stubBrowserDriver,
|
|
29
|
+
} from './runner.js';
|