Commit Graph

33 Commits

Author SHA1 Message Date
Jakub Zych
c1c9a9f853 test(11.1-06): acceptance subtests per success criterion and the final docs gate
- TestPhase11_1Acceptance asserts SC1 to SC5 on the real tree: sections
  and module pages, theme markers and no Node exec, AI outputs in sync,
  every go fence a src= copy run by go test, concept map and walkthrough
- check-phase11.1.sh --named runs every named test of the phase by exact
  name (modules' TestDocs* and output Examples derived from source) and
  refuses failures, skips, missing or renamed tests and no tests to run
- --all runs preconditions, deps, self-test, docs, forbidden, claude,
  named and the full go vet and go test
2026-10-01 00:10:12 +02:00
Jakub Zych
1d38e73f03 test(11.1-06): plant one fixture per docs checker rule and run them in the gate
- testdata/clean passes every check; 63 violation cases each overlay one
  fault and a want.txt naming the single problem it must produce
- TestPlantedViolations also plants the forbidden name (split literals)
  and symlink escapes at run time; TestBuildOutputGuard covers --out
- check-phase11.1.sh --self-test runs the corpus through a go test -json
  detector that refuses FAIL, SKIP, zero tests and no tests to run
- the self-test scratch copy now carries examples/ and README.md, so its
  baseline sees the example command literals the real tree sees
2026-09-30 23:52:19 +02:00
Jakub Zych
93c735b8a2 fix(11-08): make transaction gates fail closed 2026-09-30 22:24:12 +02:00
Jakub Zych
dd11bdb0c7 feat(11.1-02): add the documentation theme, chroma highlighting and docs:serve
- WinterCMS-style shell: header with search and theme toggle, grouped
  sidebar, on-page TOC, pager, page actions, callouts, heading
  permalinks, footer and a 404 page
- fenced code highlighted at build time by chroma/v2 into tok-* classes,
  with a copy button; no inline script, style or handler
- vendored DM Sans/DM Mono fonts and Lucide icons with their licences
- client-side search over search-index.json built with textContent only
- summer docs:serve builds into a temp dir, serves on loopback by default,
  returns 404.html with status 404 and rebuilds on change
2026-09-30 21:57:55 +02:00
Jakub Zych
5d4c1e3046 feat(11.1-02): check links, commands, forbidden names and fence policy
- relative links and anchors resolve against the renderer's heading IDs
- summer and ./bin/<app> command names come from the real command
  constructors through docsite.Options.Commands; a nil set is a problem
- consuming-application names fail in page sources and built outputs
- go fences in docs/ pages need src=, callouts are NOTE, TIP or WARNING,
  docs/ headings are plain ASCII
- gate gains --claude and self-test plants for each new rule
2026-09-30 21:40:46 +02:00
Jakub Zych
f4605292b5 feat(11.1-02): check module identifiers in docs and READMEs
- go/parser index of every modules/ package and sub-package, with methods,
  fields, interface methods and promoted members
- code spans in docs pages, module READMEs and the root README fail
  Check and docs:build when the named identifier does not exist
- scripts/check-phase11.1.sh with preconditions, deps, docs, forbidden,
  go and a self-test that plants one violation per rule
2026-09-30 21:35:56 +02:00
Jakub Zych
d4fc957f8f fix(11-08): add the T-11-31 removal check to the phase gate
- RC-14 removes the foreign-transaction refusal in lagoon.AfterCommit and
  requires TestTransactionAfterCommit to fail
2026-09-30 21:00:20 +02:00
Jakub Zych
61da4d1a4c fix(11): let the Phase 10 gate accept the Phase 12 pending goldens
- 11-06 records TestBroadcastGoldens/created and /updated and reports them
  as skipped until Phase 12; the Phase 10 detector refused any skip, so
  check-phase10.sh --all failed on the fonoteka.go suite
- mirrors 73cfed7 (check-phase10.1.sh): the detector accepts exactly those
  skips when their output carries 'pending: Phase 12'; the self-test proves
  a pending skip passes and one without the text fails
2026-09-30 15:22:00 +02:00
Jakub Zych
73cfed74ed fix(11-07): let the Phase 10.1 gate accept the Phase 12 pending goldens
- 11-06 records TestBroadcastGoldens/created and /updated and reports them
  as skipped until Phase 12; the 10.1 detector refused any skip, so
  check-phase10.1.sh --all failed on the fonoteka.go suite
- the detector now accepts exactly those skips when their output carries
  'pending: Phase 12' (the same rule check-phase11.sh enforces); the
  self-test proves a pending skip passes and one without the text fails
2026-09-30 14:55:16 +02:00
Jakub Zych
7743487b76 test(11-07): add the fail-closed Phase 11 gate and removal harness
- scripts/check-phase11.sh: --self-test, --hygiene, --go, --postgres,
  --named, --evidence, --all (prints 'phase11 all passed') and --removal
- the go test -json detector refuses failures, skips, zero tests and
  'no tests to run'; only the two Phase 12 broadcast goldens may skip, and
  only with their pending text
- hygiene refuses application names in the Phase 11 framework files, the
  Centrifugo/Typesense/Web Push client libraries, a direct cron
  requirement, River other than v0.47.0 and a module without README or
  root row; each rule returns on its first violation and the self-test
  proves each refuses its own plant and accepts look-alikes
- --removal: anchor-exact mutations for the high threats, each required to
  fail its named test on an assertion and restored byte for byte (cmp)
2026-09-30 14:42:38 +02:00
Jakub Zych
02df0a8a15 feat(10.1-04): add the fail-closed Phase 10.1 gate
scripts/check-phase10.1.sh: --self-test, --go, --security, --postgres,
--spa, --openapi, --dist, --hygiene, --evidence and --all.

- phase101_detect refuses failed, skipped, zero-test, non-JSON and
  build-failed runs and required tests that did not pass
- hygiene_101 refuses HTML-string parsers in admin/src, network, cookie
  or storage access in application plugin asset JS, and script, style or
  inline handler markup in application partial templates; each rule is
  proven by its own self-test plant
- --evidence requires a review row and, for every high threat, a named
  test and a removal check row
2026-09-29 03:13:08 +02:00
Jakub Zych
9aeb0e156b fix(10.1-04): drop the stale parity allow-list from the Phase 10 gate
TestMigrateSeedsCanonicalGenres and TestSchemaMatchesPHPSnapshot pass
since fonoteka.go 21c0f12, and the detector refuses an allow-listed
failure that passes, so check-phase10.sh --go failed. The gate now
allow-lists nothing.
2026-09-29 03:13:08 +02:00
Jakub Zych
38f087deb3 fix(10.2): exclude planning artifacts from import gate
- Align Git-backed source enumeration with the fallback scan
- Prove tracked historical imports are ignored in self-test
2026-09-28 13:35:11 +02:00
Jakub Zych
4c7d4cc4b9 test(10.2-02): add nested-layout hygiene gate
- Refuse root package directories, old imports, missing READMEs, and stale status text\n- Validate Go vet and tests across framework and Fonoteka
2026-09-28 13:18:08 +02:00
Jakub Zych
5e50b166ef refactor(10.2-01): nest framework packages under modules
- Move remaining beach packages and embedded admin assets\n- Rewrite framework, example, build, and gate paths
2026-09-28 02:21:02 +02:00
Jakub Zych
fbef773a24 test(10-05): hygiene confines browser storage and self-tests each rule
- --hygiene refuses localStorage, sessionStorage, indexedDB or document.cookie
  outside admin/src/state/useSidebar.ts (T-10-22)
- --self-test plants each violation with a scratch test import, so the
  refusal must come from that rule and not from the untested-module check
2026-09-27 18:15:05 +02:00
Jakub Zych
07edc6ca29 test(10-05): fail-closed Phase 10 gate script
- scripts/check-phase10.sh with --self-test, --go, --security, --postgres,
  --spa, --openapi, --dist, --hygiene, --evidence and --all
- phase10_detect refuses failed, skipped, zero-test, non-JSON and build-failed
  go test runs and named tests that did not pass
- the two known fonoteka parity failures are the only allow-listed ones and
  refuse the gate once they pass again
- hygiene enforces the framework/app boundary, SC-4 alias-only API types,
  typed-client-only HTTP, no raw HTML, same-origin dist, named lucide imports,
  no retired admin prefix routes and a test import for every SPA module
2026-09-27 18:10:59 +02:00
Jakub Zych
dafdb18234 feat(10-01): harden the admin cookie session and prefix boot guards
- refresh and logout read the Bearer header first, then the summer_admin
  cookie; a cookie refresh rotates the cookie without a token in the body and
  logout always expires the cookie
- backend.cookie_secure (default true) may drop Secure outside production only
- activation rejects controller vendor segments api, assets, login, settings
- BuildRouter rejects non-cabana routes at or under the admin prefix
- SPA single-flights refresh on 401, replays once, and refreshes proactively
  at 80 percent of expires_in; dist rebuilt
- scripts/check-admin-dist.sh rebuilds the SPA and fails on dist drift
- tests: TestPhase10CookieAuth, TestPhase10CSRF, TestPhase10Prefix,
  TestPhase10AdminPrefixCollision, boardwalk serving and header tests
2026-09-27 15:34:19 +02:00
Jakub Zych
5f9353841b feat(10-01): serve the embedded admin SPA at backend.uri with cookie login
- backend.uri prefix (default /backend) mounts the admin API at {prefix}/api/v1
  and the embedded SPA shell at {prefix} with an api/ JSON 404 fallback
- cookie transport: an X-Requested-With login sets the HttpOnly summer_admin
  cookie and returns no token; the backend guard reads the cookie after Bearer
- CSRF wrapper refuses cookie-only POST/PUT/DELETE without X-Requested-With
- boardwalk package embeds boardwalk/dist, rewrites index.html once per prefix
  and sets cache and security headers
- framework admin OpenAPI pipeline (swag, swagger2openapi, openapi-typescript)
  with prefix-relative paths and typed envelopes for the tracer routes
- admin/ Vite SPA: login, plugin rail, section panel and read-only list
  through the openapi-fetch client typed by the generated schema
2026-09-27 15:21:48 +02:00
Jakub Zych
4392550e23 feat(09-12): add the phase 9 acceptance gate
- Document every D-09 admin route for the OpenAPI contract.
- Fail the gate on skipped tests, zero-test runs, and a missing admin path.
2026-09-27 03:02:00 +02:00
Jakub Zych
e562bf6f5b fix(08-10): correct check-phase8-mcp-client.mjs's connected-apps field name and revoke ordering
Two real defects surfaced by the gate's first live run against the real
fonoteka-mcp SDK:

- stage_revoke looked up the connected app by a.name; ConnectedAppsIndex
  actually serializes client_name (confirmed against
  controllers/api/connected_app_controller.go serializeConnectedApp).
- Even with that fixed, stage_revoke ran after stage_replay, by which
  point RevokeLineage's forward walk (presenting the pre-refresh spent
  secret) had already cascade-revoked the live post-refresh access token
  too -- correct, intentional T-08-REFRESH-REPLAY behavior, and the exact
  same effect 08-09-PLAN.md's own mcp-lifecycle fixture ordering already
  documented ('connected-apps would already be empty if list ran after
  replay'). stage_refresh now captures the connected-app id while the
  session is still live; stage_revoke DELETEs that id directly instead of
  re-listing (ConnectedAppsDestroy has no revoked_at filter on its own
  lookup, so this still exercises the real endpoint, idempotently, against
  the id the real MCP-driven session actually owned).
2026-09-24 00:51:28 +02:00
Jakub Zych
fef037efe8 fix(08-10): close real defects found by check-phase8.sh's first end-to-end run
08-10 Task 3 is the first time this gate has actually been executed
against real Docker/Postgres/the real fonoteka CLI/the real fonoteka-mcp
process. Four independent, previously-undetected defects surfaced:

- stage_postgres never set POSTGRES_INITDB_ARGS for the ICU pl-PL locale
  lagoon.Use requires (every other Postgres testcontainer in this project
  already does); the app failed to boot at all.
- stage_app_boot's seed step POSTed to
  /_fonoteka/api/v1/onboarding/bootstrap, a route routes.go never mounts
  (its own comment marks that group deliberately empty, pending a later
  phase). The gate's test user/collection are now seeded directly with
  SQL, matching every app-level OAuth test's own real-Postgres seeding.
- phase8_workdir() assigned PHASE8_WORKDIR from inside a function body
  that is always invoked via command substitution (a subshell): the
  assignment never escaped back to the calling shell, so every separate
  caller (stage_postgres, stage_app_boot, each phase8_mcp_stage call, ...)
  minted its own fresh mktemp directory. This silently fragmented one
  run's state (app.log, the MCP client's gate-state.json) across dozens
  of directories that never saw each other's writes -- the MCP client's
  dcr stage could never see discovery's saved metadata. PHASE8_WORKDIR is
  now set once, directly, in run_full_gate before any stage runs.
- gate-state.json (the MCP client's shared cross-invocation state) holds
  raw live secrets by design and is never redacted; stage_secret_scan
  correctly flagged it. It is now deleted once the MCP lifecycle stages
  are done with it, before the scan runs -- the scan itself stays exactly
  as strict as it already was.

stage_security_review also now refuses a nonzero threats_open count or a
missing required T-08-* row, not just a missing/unverified file, and gains
--security-review-only, a focused mode for Task 2's own verify command.
2026-09-24 00:51:17 +02:00
Jakub Zych
034f63907d feat(08-10): fail-closed 08-SECURITY-REVIEW.md checks in check-phase8.sh
stage_security_review now also refuses a nonzero threats_open count and
any missing required T-08-* threat row, not just a missing/unverified
file. Adds --security-review-only, a focused mode running just this
stage (Task 2's own verify command) with no services booted.
2026-09-24 00:12:28 +02:00
Jakub Zych
e87346f9e3 feat(08-09): complete the fail-closed Phase 8 final unchanged-MCP gate
Fills in every scripts/check-phase8.sh stage skeleton with real logic:
disposable Postgres (docker run + pg_isready), the assembled Go app built
and served against it with a throwaway onboarding-seeded gate account,
the real unchanged fonoteka-mcp process started with all three required
environment variables, and the full scripted SDK lifecycle -- discovery
(MCP's own RFC 9728 401 hint, verified separately from authorization
server metadata), DCR, PKCE authorize, JWT login/consent, token, an MCP
tool call, refresh, replay of the spent refresh token, revoke, and a
post-revoke refresh failure -- delegated to the new
scripts/check-phase8-mcp-client.mjs driver, which resolves the MCP SDK's
auth helpers from fonoteka-mcp's own node_modules (no new dependency,
same pattern as parity/capture_clients.mjs). Both repositories'
vet/test/race, the full parity/corpus/secret-scan gate, the existing
check-phase8-ui.mjs --final-gate UI harness, an unchanged-client git-diff
check for both MCP_ROOT and NUXT_ROOT, and a 08-SECURITY-REVIEW.md
status:verified gate close out the stage list.

--contract-self-test validates structure only (stage names/order,
cleanup trap, loopback-only binding, the three MCP env vars, the
redaction helper, no pre-final full-run flag, read-only unchanged-client
references) in well under 30 seconds -- it boots no services. The
--red-contract self-test from Task 1 is preserved unchanged. run_full_gate
(the no-flag invocation) is 08-10 Task 3's sole execution site; 08-09
never invokes it.
2026-09-23 23:18:15 +02:00
Jakub Zych
246a488412 test(08-09): add check-phase8.sh gate skeleton with RED self-test
- Declares the ordered Phase 8 stage list and stage function skeletons
- --red-contract <stage> is a permanent RED-harness self-test hook
  (exit 86, PHASE8_STAGE:<stage>:FAIL:PHASE8_RED:real-mcp-stage)
- --contract-self-test and the full gate are completed in Task 3/08-10
2026-09-23 22:44:20 +02:00
Jakub Zych
fac9648ac9 feat(08-05): add read-only UI-contract harness for consent and connected apps
check-phase8-ui.mjs encodes 08-UI-SPEC.md's full consent/connected-app
state matrix, accessibility, responsive, and i18n contract as a versioned
32-scenario catalog across 7 categories. --contract-self-test validates
catalog completeness, guarded Nuxt source-file hashes (proving the
harness itself never writes inside vue-fonoteka-app), and that
@playwright/test resolves from the already-installed dependency, all
without booting a browser or service (runs in ~50ms).

--final-gate (running verify:oauth-return-path, verify:oauth-i18n, and
the real Playwright matrix) is scaffolded but refuses to run without
PHASE8_UI_ALLOW_FINAL_GATE=1 and is explicitly 08-10's closing-checkpoint
responsibility, not executed by this plan.
2026-09-23 21:04:34 +02:00
Jakub Zych
24d35d85e8 test(08-01): add failing RFC 8414 metadata RED test and fail-closed verifier
- wristband.Server.Metadata is a compiling 501 stub; TestPhase8RedMetadata
  asserts the exact unwrapped PHP metadata document, headers and status and
  fails with the PHASE8_RED:metadata sentinel (D-06)
- scripts/check-phase8-red.sh implements the shared go/shell RED contract
  for the rest of Phase 8: exact selected test/package failure plus sentinel,
  rejecting unrelated fail actions, compile/setup failures, panics,
  malformed JSON, missing/duplicate sentinels and zero selection (D-04/D-18)
2026-09-23 19:09:14 +02:00
Jakub Zych
9f6fbadce8 test(04-04): close mail safety and Mailpit SMTP receipt coverage
- Assert memory recipients, HTML safety, and SMTP TLS without credential leaks
- Prove real SMTP delivery through Mailpit HTTP API when Docker is available
- Add scripts/check-phase4.sh as the phase vet, test, race, and SMTP gate

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-18 14:12:28 +02:00
Jakub Zych
fda61f0c15 fix(03-04): keep Phase 3 gate on Go and CLI regression
The Phase 2 PHP self-replay currently fails four wishlist album_count
routes that this slice did not change. The Phase 3 script now re-runs
TestParitySynthetic and the CLI record/replay smoke instead of
check-phase2.sh --fresh-php.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 20:39:45 +02:00
Jakub Zych
c2dfa7b62f test(03-04): add repeatable Phase 3 check script
- Root and app vet/test/race plus focused genres parity and corpus audit
- Refuses missing Docker and runs the Phase 2 --fresh-php regression

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 20:33:00 +02:00
Jakub Zych
066c3d3ab7 fix(02-05): wait for MariaDB with hex-only process credentials
- Avoid urlsafe passwords that start with a dash and break mariadbadmin -p
- Probe readiness with a quoted SQL SELECT against the disposable container

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:12:05 +02:00
Jakub Zych
a296e98d8e feat(02-05): add the repeatable Phase 2 vet, race and PHP gate
- Check root and fonoteka.go with vet, test and race plus TestParitySynthetic
- Audit the 154-route corpus and smoke parity:record/replay against loopback
- Provision a disposable MariaDB, pin PHP to 127.0.0.1:8423, and self-replay seed, routes and clients

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 14:09:16 +02:00
Jakub Zych
dc7997e45c test(01-04): cover tool, output, watch loop and workspace modules
- Non-TTY widgets/prompts, flag parsing, secret non-leak and malicious IDs
- Real hello workspace rebuild latency line, debounce and ignored bin/tmp
- scripts/check-phase1.sh runs vet/test/race across root, hello, base, greeter, optional
2026-09-16 14:14:05 +02:00