You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Restore canonical frontend behavior coverage and SAM parity gates
Status: accepted — current-main integration delta passed Architecture, Tester, and PM on frozen fingerprint a0d7171096014709e5f3f1722033195131e64872ca586a6aebc8fd3a9f0e1019; ready for Software Engineer integration commit
Tags: bug, portal, frontend, backend, infra, testing, design, P0
Parent: #148
Depends on: None for local source implementation — the #156 prerequisite is satisfied at exact current main 3ad9e9c3e81243b30f42aed5b72b6c9b34777902
Blocks: #158, final deployed acceptance in #155, and closure of #148
Next owner: Software Engineer — commit the exact accepted integration candidate on base f8b4a19a521d18f878e92af65d998e9af99a5b17 with Closes #159; do not change the frozen fingerprint
Scope
Restore the verification that was lost during the canonical-frontend cutover, without restoring any retired SPA. Top-level frontend/ remains the only browser UI and the existing TypeScript backend remains its only server. This issue adds a public-safe capability/coverage contract, behavior-level tests for every retained operator surface, a deterministic deployment allowlist, and a mandatory post-SAM-build parity/runtime gate.
The implementation baseline is exact clean main at 3ad9e9c3e81243b30f42aed5b72b6c9b34777902, containing shipped #157 and accepted/integrated #156. Its Check DataOps v1 app source job passed in run 31541797073, covering backend tests, the Sponsor gate, typecheck, backend build, the full E2E suite, and SAM validation/build. #159 runs next because it owns the shared frontend test harness, packaging verifier, Makefile, and normal CI gate. #158 follows #159 and remains the sole owner of assistant lifecycle, concurrency, provider mediation, and artifact-access product changes; this issue proves only the retained assistant list/detail/deep-link baseline and must not preimplement or redefine #158.
Canonical capability and coverage matrix
All fixtures, names, IDs, documents, providers, and evidence are synthetic and public-safe. O/A means an enabled authenticated operator or admin unless a stricter role is stated. Signed-out, expired, and disabled sessions must be denied by the shared browser-cookie boundary; /api/* and /work/api/* failures remain JSON and never return SPA HTML.
Capability / canonical route
Real API seam
Role and states that must be proved
Required behavior coverage
Session and Settings (/#/, Settings)
/login, /logout, /api/me
signed out, expired/disabled, O/A
browser-cookie login redirect, visible logout, no bearer/local-storage fallback, desktop/mobile Settings focus and close
server-derived role controls, a real admin mutation and spoofed/operator denial without side effect
For every row, the focused browser suite must use the normal local backend and in-memory DynamoDB/docs fixture path. It must assert route, accessible visible state, API response/side effect, reload or return navigation, and a meaningful empty/error/recovery state. Request interception, browser-only payload mocks, source-string/selector-presence assertions, snapshots without behavior assertions, and screenshots alone do not count. Existing stronger suites such as #156 and #157 may satisfy a cell when they are retained and run in the normal E2E command; the matrix must point to the exact test title/file. No cell may say “covered later.”
frontend/DESIGN.md and frontend/Dockerfile remain source/development files and must not be packaged. There is no transform: each packaged allowlisted file must be byte-identical to its top-level frontend/ source counterpart. Within the deployable UI subtree dist/frontend/, the inventory is exactly the three allowlisted regular files: there is no other entry, symlink, or non-regular file. Outside that subtree, no application-owned alternate UI candidate or browser entry may exist under pages/, public/, static/, assets/, or another frontend directory.
Actual SAM dependency contents under node_modules/ legitimately include HTML files and symlinks such as node_modules/.bin/ entries and package links. Dependency-owned entries are not browser entrypoints merely because of their filename or extension. They must be inventoried deterministically, with dependency symlinks/non-regular entries recorded and never followed; they must never satisfy the UI allowlist, mask or alias an alternate UI root, or cause legitimate dependency HTML to be misclassified as an application frontend.
backend/scripts/verify-frontend-artifact.mjs must require explicit --source and --artifact roots and recursively inventory the artifact deterministically using normalized relative POSIX paths. It must compare the exact UI allowlist and bytes and fail closed on unreadable/missing roots, missing allowlisted source/artifact files, and byte drift. Extra entries, duplicate content or filename, symlinks/non-regular files, alternate entrypoints, and forbidden trees fail when they occur in the deployable UI subtree or an application-owned alternate-UI candidate. The verifier must distinguish the dependency inventory under node_modules/: legitimate dependency HTML and expected dependency symlinks are inventoried but not followed and are not rejected solely for being dependency entries. It must never silently default to backend/dist, the current working directory, or a neighboring checkout.
The same verifier gates both backend/dist after npm --prefix backend run build and .aws-sam/build/BackendFunction immediately after make sam-build. make ci and the normal .github/workflows/deploy-dataops-v1.yml checks and deploy jobs must run the post-build SAM gate before any deploy step. A build or workflow cannot continue if parity fails.
An isolated copy of .aws-sam/build/BackendFunction under .tmp/issue-159/ must run with FRONTEND_ROOT unset and no access to repository frontend/. Its compiled handler must serve /, an extensionless/hash deep link, /src/app.js, and /src/styles.css from the packaged files with correct content and type. Missing assets, traversal, unknown static paths, /public/*, and /api/* must fail with their explicit safe page/static/JSON semantics and never fall through to another shell.
Acceptance Criteria
The capability matrix above is implemented as durable repository-owned test mapping with no missing/unclassified retained surface; every row has real API/browser behavior coverage and an exact test pointer.
The deployable UI inventory is exactly the three allowlisted regular files, byte-identical to frontend/. Within that UI subtree, development-only files, extras, duplicates, symlinks/non-files, and alternate entrypoints are absent; no application-owned alternate-UI candidate exists elsewhere. Dependency-owned node_modules/ entries do not count toward or weaken this UI allowlist.
Focused verifier tests prove exact success plus fail-closed missing source/artifact, byte drift, duplicate, alternate pages/public/other HTML, extra frontend file, symlink/non-file, bad root, and omitted-argument cases, with UI faults scoped to the deployable UI subtree and application-owned alternate-UI candidates. A representative dependency tree containing legitimate node_modules/ HTML plus node_modules/.bin/ and package symlinks passes classification only when those entries are inventoried and never followed.
backend/dist parity passes immediately after backend build and actual .aws-sam/build/BackendFunction parity passes immediately after SAM build.
Local make ci and both normal deploy-workflow build paths enforce the post-SAM-build verifier before deployment. Workflow/Makefile contract tests fail if that ordering or command is removed.
The isolated positive/negative packaged-runtime tests prove self-contained serving and no page/API fallback as specified.
The same behavior/evidence spec runs against source mode and the isolated SAM artifact with identical synthetic fixture seed, IDs, Europe/Berlin clock, locale, fonts, reduced motion, animation disablement, and browser engine; route, visible state, mutation result, accessible-name summary, console/page errors, and asset hashes match.
The exact paired screenshot inventory below is captured from the final frozen candidate; dimensions, target/state identity, and pairing are machine-checked, and Designer and Tester read every image.
Architecture PASS, Designer PASS, Tester PASS, and PM ACCEPTED are bound to the exact same final candidate fingerprint.
Tests, logs, manifests, and screenshots remain synthetic/public-safe and gitignored under .tmp/; no raw SOP, private link, contact, credential, production identifier, sponsor/finance detail, or generated operational artifact enters the public repo.
Exact paired browser evidence
Run these ten evidence states against both targets source and sam, and both viewports desktop-1440x900 and mobile-390x844:
The output directory is .tmp/screenshots/issue-159/. Its inventory must be exactly the 40-file cross-product named <target>-<state>-<viewport>.png (for example source-home-ready-desktop-1440x900.png and sam-home-ready-desktop-1440x900.png), with no stale extra image. Each source/SAM pair uses the same seeded state immediately before capture. Pixel similarity is supporting evidence only; DOM, behavior, asset-byte, console, and accessibility assertions are mandatory.
Test Scenarios
Scenario: Every retained surface has real coverage
Given: the synthetic O/A role fixtures and matrix states above
When: the normal browser suite drives each route through the real local API and reload/return path
Then: every matrix row proves its visible behavior, side effect or denial, and recovery state without request interception or marker-only assertions
Scenario: Exact source/build/SAM inventory
Given: a clean backend build and SAM build
When: the explicit verifier inventories backend/dist and .aws-sam/build/BackendFunction
Then: the deployable UI subtree contains only the three allowlisted regular files, each matches source bytes, and no application-owned alternate UI entrypoint exists; dependency-owned entries are inventoried separately and no dependency link is followed or used to satisfy the UI contract
Scenario: Artifact faults fail closed
Given: isolated copies with, one at a time, a missing UI file, changed UI byte, UI-subtree duplicate or extra file, UI symlink/non-file, application-owned alternate HTML/public/pages/UI tree, invalid root, or omitted argument, plus a positive dependency copy containing legitimate node_modules/ HTML and node_modules/.bin/ or package symlinks
When: verification and relevant runtime requests run
Then: every fault case exits non-zero or returns the specified safe non-success response with no fallback shell or leaked file, while the dependency-positive case passes only with those dependency entries inventoried, classified outside the UI allowlist, and never followed
Scenario: Source and SAM browser parity
Given: identical deterministic fixtures and the exact final candidate
When: the same evidence journey runs from source and the isolated SAM handler at both viewports
Then: assets, route/state, mutation outcome, accessible summary, console/error result, and the exact 40-image evidence inventory match
Required Verification
Run in this order and report exact commands, exit codes, test counts, artifact inventory/digests, and screenshot paths:
npm --prefix backend test
npm --prefix backend run typecheck
npm --prefix backend run build
node backend/scripts/verify-frontend-artifact.mjs --source frontend --artifact backend/dist
npm --prefix backend run test:e2e
npm --prefix backend run test:frontend-artifact
make sam-validate
make sam-build
node backend/scripts/verify-frontend-artifact.mjs --source frontend --artifact .aws-sam/build/BackendFunction
npm --prefix backend run test:e2e:frontend-parity
make ci
git diff --check
The named focused scripts are deliverables of this issue and must be non-interactive. test:frontend-artifact owns isolated verifier/runtime positive and negative cases. test:e2e:frontend-parity owns the same-source/same-SAM behavior and exact evidence run. All SAM operations are local builds/validation with project-local empty AWS config where applicable; they must not deploy or call AWS APIs.
Dependency Resume Condition
#157 is shipped and the #156 source prerequisite is satisfied. #156 received Tester PASS and PM ACCEPTED, was committed at acdd2c8ccfa88f1d46fd0221b90713f84a1046f3, and was integrated by merge 45d98c5de65466ea2f7d8a0ce2da1eaa8acfbedb. Exact current main 3ad9e9c3e81243b30f42aed5b72b6c9b34777902, which contains that integration on top of #157, passed the Check DataOps v1 app source job in run 31541797073: backend tests, Sponsor gate, typecheck, backend build, full E2E, and SAM validation/build all succeeded. This is the applicable source On-Call result and formally resumes #159.
The Software Engineer must create a fresh #159 worktree from exact clean main 3ad9e9c3e81243b30f42aed5b72b6c9b34777902; do not reuse the stale 56a1e2abd3f803172ea78bc9cd511bacc3733c31 baseline or any pre-integration candidate. Later deployment attempts and the external/pre-existing deployment blockers tracked by #155/#136/#143/#147/#160 do not block local #159 implementation, review, merge, or source CI, and this resume does not claim deployed acceptance.
#159 must integrate before #158 starts because both touch canonical frontend/E2E infrastructure and #158 should extend the final parity baseline rather than fork it. #158 remains the owner of all assistant lifecycle/access-policy behavior.
Restoring backend/src/pages/, backend/src/public/, retired tests/selectors as product code, the legacy SPA/router, a fallback switch, a parallel/third UI, or another frontend framework.
Broad visual/IA redesign, new product capabilities, new roles/ACLs, data migration, operational/private knowledge, or edits to source repos outside dataops.
Manual deploy, workflow dispatch/rerun, AWS/IAM/CloudFormation mutation, external provider call, real assistant execution, publishing, sending, or GitHub content mutation.
Restore canonical frontend behavior coverage and SAM parity gates
Status: accepted — current-main integration delta passed Architecture, Tester, and PM on frozen fingerprint
a0d7171096014709e5f3f1722033195131e64872ca586a6aebc8fd3a9f0e1019; ready for Software Engineer integration commitTags:
bug,portal,frontend,backend,infra,testing,design,P0Parent: #148
Depends on: None for local source implementation — the #156 prerequisite is satisfied at exact current main
3ad9e9c3e81243b30f42aed5b72b6c9b34777902Blocks: #158, final deployed acceptance in #155, and closure of #148
Next owner: Software Engineer — commit the exact accepted integration candidate on base
f8b4a19a521d18f878e92af65d998e9af99a5b17withCloses #159; do not change the frozen fingerprintScope
Restore the verification that was lost during the canonical-frontend cutover, without restoring any retired SPA. Top-level
frontend/remains the only browser UI and the existing TypeScript backend remains its only server. This issue adds a public-safe capability/coverage contract, behavior-level tests for every retained operator surface, a deterministic deployment allowlist, and a mandatory post-SAM-build parity/runtime gate.The implementation baseline is exact clean
mainat3ad9e9c3e81243b30f42aed5b72b6c9b34777902, containing shipped #157 and accepted/integrated #156. ItsCheck DataOps v1 appsource job passed in run 31541797073, covering backend tests, the Sponsor gate, typecheck, backend build, the full E2E suite, and SAM validation/build. #159 runs next because it owns the shared frontend test harness, packaging verifier, Makefile, and normal CI gate. #158 follows #159 and remains the sole owner of assistant lifecycle, concurrency, provider mediation, and artifact-access product changes; this issue proves only the retained assistant list/detail/deep-link baseline and must not preimplement or redefine #158.Canonical capability and coverage matrix
All fixtures, names, IDs, documents, providers, and evidence are synthetic and public-safe.
O/Ameans an enabled authenticated operator or admin unless a stricter role is stated. Signed-out, expired, and disabled sessions must be denied by the shared browser-cookie boundary;/api/*and/work/api/*failures remain JSON and never return SPA HTML./#/, Settings)/login,/logout,/api/me/#/)/api/tasks,/api/bundles,/api/notifications,/docs/process-quality/#/inbox?intakeId=)/api/intake/#/tasks?...)/api/tasks,/api/files,/api/artifacts,/docs,/content/*/#/bundles?...)/api/bundles,/api/tasks,/api/artifacts/#/templates,/#/recurring)/api/templates,/api/recurring/#/assistants?assistantJobId=)/api/assistant-jobs,/api/artifacts/#/artifacts)/api/artifacts,/api/files/#/notifications)/api/notifications/#/bookkeeping)/api/bookkeeping/*/#/sponsors?bookingId=)/api/sponsor-crm/*/#/newsletter)/api/newsletter-slots/#/calendar)/api/calendar-items/#/mailing-exports)/api/mailing-exports/#/processes)/docs,/search,/content/*,/docs/registry,/docs/backlinks/#/admin)/docs/process-quality,/git/status,/git/log/#/users)/api/users,/api/meFor every row, the focused browser suite must use the normal local backend and in-memory DynamoDB/docs fixture path. It must assert route, accessible visible state, API response/side effect, reload or return navigation, and a meaningful empty/error/recovery state. Request interception, browser-only payload mocks, source-string/selector-presence assertions, snapshots without behavior assertions, and screenshots alone do not count. Existing stronger suites such as #156 and #157 may satisfy a cell when they are retained and run in the normal E2E command; the matrix must point to the exact test title/file. No cell may say “covered later.”
Deterministic artifact contract
The deployment UI allowlist is exactly:
frontend/DESIGN.mdandfrontend/Dockerfileremain source/development files and must not be packaged. There is no transform: each packaged allowlisted file must be byte-identical to its top-levelfrontend/source counterpart. Within the deployable UI subtreedist/frontend/, the inventory is exactly the three allowlisted regular files: there is no other entry, symlink, or non-regular file. Outside that subtree, no application-owned alternate UI candidate or browser entry may exist underpages/,public/,static/,assets/, or another frontend directory.Actual SAM dependency contents under
node_modules/legitimately include HTML files and symlinks such asnode_modules/.bin/entries and package links. Dependency-owned entries are not browser entrypoints merely because of their filename or extension. They must be inventoried deterministically, with dependency symlinks/non-regular entries recorded and never followed; they must never satisfy the UI allowlist, mask or alias an alternate UI root, or cause legitimate dependency HTML to be misclassified as an application frontend.backend/scripts/verify-frontend-artifact.mjsmust require explicit--sourceand--artifactroots and recursively inventory the artifact deterministically using normalized relative POSIX paths. It must compare the exact UI allowlist and bytes and fail closed on unreadable/missing roots, missing allowlisted source/artifact files, and byte drift. Extra entries, duplicate content or filename, symlinks/non-regular files, alternate entrypoints, and forbidden trees fail when they occur in the deployable UI subtree or an application-owned alternate-UI candidate. The verifier must distinguish the dependency inventory undernode_modules/: legitimate dependency HTML and expected dependency symlinks are inventoried but not followed and are not rejected solely for being dependency entries. It must never silently default tobackend/dist, the current working directory, or a neighboring checkout.The same verifier gates both
backend/distafternpm --prefix backend run buildand.aws-sam/build/BackendFunctionimmediately aftermake sam-build.make ciand the normal.github/workflows/deploy-dataops-v1.ymlchecks and deploy jobs must run the post-build SAM gate before any deploy step. A build or workflow cannot continue if parity fails.An isolated copy of
.aws-sam/build/BackendFunctionunder.tmp/issue-159/must run withFRONTEND_ROOTunset and no access to repositoryfrontend/. Its compiled handler must serve/, an extensionless/hash deep link,/src/app.js, and/src/styles.cssfrom the packaged files with correct content and type. Missing assets, traversal, unknown static paths,/public/*, and/api/*must fail with their explicit safe page/static/JSON semantics and never fall through to another shell.Acceptance Criteria
frontend/. Within that UI subtree, development-only files, extras, duplicates, symlinks/non-files, and alternate entrypoints are absent; no application-owned alternate-UI candidate exists elsewhere. Dependency-ownednode_modules/entries do not count toward or weaken this UI allowlist.pages/public/other HTML, extra frontend file, symlink/non-file, bad root, and omitted-argument cases, with UI faults scoped to the deployable UI subtree and application-owned alternate-UI candidates. A representative dependency tree containing legitimatenode_modules/HTML plusnode_modules/.bin/and package symlinks passes classification only when those entries are inventoried and never followed.backend/distparity passes immediately after backend build and actual.aws-sam/build/BackendFunctionparity passes immediately after SAM build.make ciand both normal deploy-workflow build paths enforce the post-SAM-build verifier before deployment. Workflow/Makefile contract tests fail if that ordering or command is removed..tmp/; no raw SOP, private link, contact, credential, production identifier, sponsor/finance detail, or generated operational artifact enters the public repo.Exact paired browser evidence
Run these ten evidence states against both targets
sourceandsam, and both viewportsdesktop-1440x900andmobile-390x844:The output directory is
.tmp/screenshots/issue-159/. Its inventory must be exactly the 40-file cross-product named<target>-<state>-<viewport>.png(for examplesource-home-ready-desktop-1440x900.pngandsam-home-ready-desktop-1440x900.png), with no stale extra image. Each source/SAM pair uses the same seeded state immediately before capture. Pixel similarity is supporting evidence only; DOM, behavior, asset-byte, console, and accessibility assertions are mandatory.Test Scenarios
Scenario: Every retained surface has real coverage
Given: the synthetic O/A role fixtures and matrix states above
When: the normal browser suite drives each route through the real local API and reload/return path
Then: every matrix row proves its visible behavior, side effect or denial, and recovery state without request interception or marker-only assertions
Scenario: Exact source/build/SAM inventory
Given: a clean backend build and SAM build
When: the explicit verifier inventories
backend/distand.aws-sam/build/BackendFunctionThen: the deployable UI subtree contains only the three allowlisted regular files, each matches source bytes, and no application-owned alternate UI entrypoint exists; dependency-owned entries are inventoried separately and no dependency link is followed or used to satisfy the UI contract
Scenario: Artifact faults fail closed
Given: isolated copies with, one at a time, a missing UI file, changed UI byte, UI-subtree duplicate or extra file, UI symlink/non-file, application-owned alternate HTML/public/pages/UI tree, invalid root, or omitted argument, plus a positive dependency copy containing legitimate
node_modules/HTML andnode_modules/.bin/or package symlinksWhen: verification and relevant runtime requests run
Then: every fault case exits non-zero or returns the specified safe non-success response with no fallback shell or leaked file, while the dependency-positive case passes only with those dependency entries inventoried, classified outside the UI allowlist, and never followed
Scenario: Source and SAM browser parity
Given: identical deterministic fixtures and the exact final candidate
When: the same evidence journey runs from source and the isolated SAM handler at both viewports
Then: assets, route/state, mutation outcome, accessible summary, console/error result, and the exact 40-image evidence inventory match
Required Verification
Run in this order and report exact commands, exit codes, test counts, artifact inventory/digests, and screenshot paths:
npm --prefix backend test npm --prefix backend run typecheck npm --prefix backend run build node backend/scripts/verify-frontend-artifact.mjs --source frontend --artifact backend/dist npm --prefix backend run test:e2e npm --prefix backend run test:frontend-artifact make sam-validate make sam-build node backend/scripts/verify-frontend-artifact.mjs --source frontend --artifact .aws-sam/build/BackendFunction npm --prefix backend run test:e2e:frontend-parity make ci git diff --checkThe named focused scripts are deliverables of this issue and must be non-interactive.
test:frontend-artifactowns isolated verifier/runtime positive and negative cases.test:e2e:frontend-parityowns the same-source/same-SAM behavior and exact evidence run. All SAM operations are local builds/validation with project-local empty AWS config where applicable; they must not deploy or call AWS APIs.Dependency Resume Condition
#157 is shipped and the #156 source prerequisite is satisfied. #156 received Tester PASS and PM ACCEPTED, was committed at
acdd2c8ccfa88f1d46fd0221b90713f84a1046f3, and was integrated by merge45d98c5de65466ea2f7d8a0ce2da1eaa8acfbedb. Exact current main3ad9e9c3e81243b30f42aed5b72b6c9b34777902, which contains that integration on top of #157, passed theCheck DataOps v1 appsource job in run 31541797073: backend tests, Sponsor gate, typecheck, backend build, full E2E, and SAM validation/build all succeeded. This is the applicable source On-Call result and formally resumes #159.The Software Engineer must create a fresh #159 worktree from exact clean main
3ad9e9c3e81243b30f42aed5b72b6c9b34777902; do not reuse the stale56a1e2abd3f803172ea78bc9cd511bacc3733c31baseline or any pre-integration candidate. Later deployment attempts and the external/pre-existing deployment blockers tracked by #155/#136/#143/#147/#160 do not block local #159 implementation, review, merge, or source CI, and this resume does not claim deployed acceptance.#159 must integrate before #158 starts because both touch canonical frontend/E2E infrastructure and #158 should extend the final parity baseline rather than fork it. #158 remains the owner of all assistant lifecycle/access-policy behavior.
Lifecycle Gates
3ad9e9c3e81243b30f42aed5b72b6c9b34777902, run 31541797073Closes #159Out of Scope
backend/src/pages/,backend/src/public/, retired tests/selectors as product code, the legacy SPA/router, a fallback switch, a parallel/third UI, or another frontend framework.dataops.[HUMAN]gate: all Restore canonical frontend behavior coverage and SAM parity gates #159 acceptance is local and agent-verifiable. Deployed acceptance remains separately tracked in Verify the canonical frontend through normal DataOps deployment #155.