Skip to content

refactor(gst): make an unbound refusal impossible to construct - #357

Closed
lamemustafa wants to merge 3 commits into
tapish-codex/target-status-behaviourfrom
tapish-codex/refusal-binding-token
Closed

lamemustafa wants to merge 3 commits into
tapish-codex/target-status-behaviourfrom
tapish-codex/refusal-binding-token

Conversation

@lamemustafa

Copy link
Copy Markdown
Owner

Summary

Makes recording a portal refusal without checking the visible page impossible to
construct
, rather than something three emitters each had to remember.

Sixth in the stack, on top of #356. No behaviour change intended: every emitter already
ran the guard. This removes the possibility that a fourth one does not.

Root Cause / Decision Record

What failed. Recording a refusal resolves a target outright -- the period is
answered, the run advances, and no artifact ever follows to corroborate it. The visible
page is therefore the whole of the evidence. Four separate defects across this stack were
one shape: a refusal read from a page nobody had checked against the target. Each was
found only after the previous fix shipped, because each fix reached the instance and not
the class.

Why this is the smallest safe fix. The alternative is what has been happening: a
reviewer finds the next emitter, one round at a time. declinedArtifactStep now takes
proof as its first argument, and the only values of that type come from a binder in the
same module. The brand is a type-only symbol exported nowhere, so no object literal
written elsewhere satisfies it.

Honest limit. A deliberate as unknown as VisibleTargetBinding still gets through.
This makes the check impossible to forget -- which is how all four defects happened --
not impossible to circumvent on purpose. That is stated in the module comment too.

What it closes. No open thread directly; it removes the class behind
#353 r3985770792, #354 r3985765483, #355 r3985794277, and the original #355
observation-path defect, so a fifth instance cannot be written.

Scope

  • Runtime: new filed-returns-declined-artifact.ts; the three emitters in
    filed-returns-post-click-blocked-state.ts and gstr2b-flow.ts;
    filed-returns-durable-status.ts reads the wording from the same table;
    filed-returns-durable-signals.ts registers the binding signals by derivation.
  • Tests: tests/connectors/filed-returns-declined-artifact.test.ts.
  • Docs/governance: none.
  • Explicitly out of scope: typing safeSignals beyond string[] (190 call sites, 40
    modules) -- the same class one level wider, and its own change.

Pack Workflow Preflight

  • pnpm workflow:preflight was run before editing/push, or the skip reason is documented.
  • This PR was opened from a Pack branch, not master.
  • I checked latest master Pack AGENTS guidance or recorded the stale-guidance warning.
  • PR body keeps the required Pack privacy/review/verification checklist visible.

Sanchika Adoption Gate

  • If this PR consumes @sanchika/* packages or copied Sanchika guidance, I
    read sanchika/docs/adoption-pack.md in the coordinated parent worktree.
  • If this PR consumes Sanchika, it links ComplyEaze and Axal completion evidence
    and records the Sanchika commit or copied guidance used.
  • This PR does not import ../sanchika, sanchika/packages/*/src, or parent
    source paths.

Privacy And Data-Flow Impact

  • No new browser permissions.
  • No new host permissions.
  • No new network calls.
  • No analytics, telemetry, ads, or session replay.
  • No credential, OTP, CAPTCHA, cookie, token, GST file, or taxpayer-data capture.
  • Public copy and privacy declarations are updated if behaviour changed.

Sensitive Surface Review

  • Current tab / portal target binding is preserved or intentionally changed.
  • Download completion remains evidence-backed and fail-closed.
  • Ambiguous side-effect delivery cannot be reported as confirmed success.
  • Service-worker durability impact is understood and documented.
  • Real taxpayer data, local paths, raw URLs/referrers, and portal HTML are absent from the diff.

Chrome Web Store Impact

  • This PR does not expand beyond the existing Chrome Web Store V0 listing unless every gate in docs/PUBLICATION_READINESS.md is checked.
  • Full fiscal year remains source-only and excluded from the next packaged Store build until its evidence gates are recorded.
  • Store copy, README status, Privacy QA, and reviewer instructions were reviewed if user-facing behavior changed.
  • CI ZIP creation, provenance, and protected publishing are treated as release evidence, not manual store-submission sign-off.
  • PR title uses Conventional Commits so Release Please can bump Pack after merge.

Verification

  • pnpm install --frozen-lockfile
  • pnpm audit --audit-level high
  • pnpm exec wxt prepare
  • pnpm exec prettier --check .
  • pnpm exec eslint . --max-warnings 0
  • pnpm exec tsc --noEmit
  • pnpm exec vitest run
  • pnpm exec wxt build
  • node scripts/verify-extension-package.mjs .output/chrome-mv3
  • pnpm exec wxt zip
  • node scripts/verify-extension-zip.mjs
  • node scripts/write-release-provenance.mjs
  • node scripts/verify-github-release-assets.mjs --tag <tag> --zip <zip> --checksum <sha256> --provenance <json> when release assets exist
  • node scripts/publish-chrome-web-store.mjs --zip .output/<zip> --provenance .output/pack-release-provenance.v1.json --publisher-id <id> --dry-run true
  • git diff --check
  • pnpm review:gate -- --strict-head-review --wait-head-review-ms 180000 before merge/readiness claim; a missing Codex review blocks readiness:

Artifact Evidence

  • CI run: pending on this head.
  • ZIP artifact / SHA-256: not a release PR.
  • Clean source/tag or head SHA: 319d4ec.

Local gates on 319d4ec, quoted verbatim:

prettier=0
eslint=0
tsc=0
 Test Files  182 passed (182)
      Tests  3385 passed (3385)

Base (dc67c92) was 181 files / 3379 tests. An earlier run of the same suite showed 19
failures in tests/scripts/publish-review-gate-check.test.ts; that file spawns
subprocesses and flakes under parallel load on this machine -- it was reproduced on an
untouched base earlier in this stack, and this diff does not touch it.

The guarantee is verified at compile time, so its test is too. The test file carries
two @ts-expect-error forgeries; tsc --noEmit fails if either stops being an error.
Removing the brand makes one of them unused and tsc reports
TS2578: Unused '@ts-expect-error' directive -- that is the mutation proving the brand is
what enforces the rule, not the comment above it.

PR Review Follow-Up

  • GitHub Actions completed.
  • Autogenerated Codex/bot review comments inspected after checks completed for the latest head SHA.
  • Inline review threads are resolved, outdated, or answered with evidence.
  • No commits were pushed after the last required human/bot review without re-review.
  • Any follow-up PRs or issues are listed here instead of being left implicit.
Thread/comment Disposition Commit or evidence
(none yet -- first review round)

Two things worth checking rather than assuming:

  1. The declined results now also carry the binding signal
    (gstr2b-visible-period-verified / filed-gstr1-detail-period-verified), so the
    durable record says how the refusal was checked. filed-gstr1-detail-period-verified
    is new. It is registered by derivation -- REFUSAL_BINDING_SIGNALS is spread into the
    durable allowlist -- because writing one by hand is exactly how seven correctly
    answered periods came back as needs-review earlier in this stack.
  2. The GSTR-2B safe message and retry wording were written out in both emitters, identical
    in both. They are now one Record over the declined signals, so a third refusal cannot
    be registered without deciding what a reader is told.

Screenshots

None -- no user-visible surface changed.

Recording a refusal resolves a target outright: the period is answered, the run
advances, and no artifact ever follows to corroborate it. The visible page is
therefore the whole of the evidence, and a refusal read from a page that was
never checked against the target is a wrong answer that looks exactly like a
right one.

Three emitters each learned that separately -- one reported defect at a time,
across three pull requests -- and nothing stopped a fourth from not learning it.
The check is no longer something an emitter remembers: `declinedArtifactStep`
takes proof as its first argument, and the only values of that type come from a
binder in this module.

The brand is a type-only symbol exported nowhere, so no object literal written
elsewhere satisfies it. A deliberate double assertion would still get through;
this makes the check impossible to forget, which is how all four defects
happened, not impossible to circumvent on purpose.

Two duplicates go with it. The GSTR-2B safe message and its retry wording were
written out in both emitters, identical in both, with nothing able to contradict
them -- no test compares one emitter's copy with another's. They are now a
`Record` over the declined signals, so a third refusal cannot be registered
without deciding what a reader is told and what they are offered.

The binding signals register by derivation. Writing one by hand is how seven
periods a live run had correctly answered came back as needs-review: one
unregistered token rejects the entire array it travels in, and a refusal is a
terminal step whose signals are persisted.
No behaviour change intended. Each emitter already ran a guard and built its own
result; each now presents the guard's proof and asks for the result to be built.

The flow path keeps its extra step: a stale panel is not merely refused there,
it is navigated away from, because the run still needs the period it asked for.

`filed-returns-durable-status` reads the declined wording from the same table
rather than importing a constant that said it a second time.
The guarantee is a compile-time one, so the test is too: `tsc --noEmit` fails if
either forgery below stops being an error. Removing the brand makes the
`@ts-expect-error` unused, which is the mutation that proves it holds.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 12, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-12T07:47:43.001181Z 319d4ec PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 319d4ece0b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/connectors/gst/filed-returns-declined-artifact.ts
@lamemustafa

Copy link
Copy Markdown
Owner Author

The corrected consolidated candidate is #359, based directly on master. This PR is retained as draft with its commits and review history intact; its unchanged head is not independently merge-ready. The #359 body maps every original automated ask to specific source/test evidence or an explicit held follow-up. Authenticated runtime qualification remains required before merging the replacement.

@lamemustafa
lamemustafa marked this pull request as draft September 12, 2026 11:12
@lamemustafa

Copy link
Copy Markdown
Owner Author

Superseded by #359. Its disposition register records the final status of this draft’s review asks. This draft is being closed; resolving its remaining threads marks them superseded, not fixed on this unchanged branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant