Skip to content

fix(gst): acquire filed GSTR-1 artifacts from the surfaces the portal offers - #353

Closed
lamemustafa wants to merge 10 commits into
masterfrom
tapish-codex/gstr1-artifact-surfaces
Closed

fix(gst): acquire filed GSTR-1 artifacts from the surfaces the portal offers#353
lamemustafa wants to merge 10 commits into
masterfrom
tapish-codex/gstr1-artifact-surfaces

Conversation

@lamemustafa

Copy link
Copy Markdown
Owner

Summary

Three filed-GSTR-1 acquisition defects found in a live authorised run, plus a diagnostic that made the
next one findable in one round instead of three.

The filed GSTR-1 detail route can carry the download control itself, labelled DOWNLOAD FILED (PDF),
with no View Summary control anywhere on the page. Navigating away from a page that already offered the
download is what left the flow waiting until its step limit.

Observer signals now read their control patterns from the return descriptors instead of restating them.
This file carried its own copies, so a label the descriptor learned about stayed unrecognised here — which is
how one label was missed by both layers at once.

A live NIL GSTR-1 summary envelope is smaller than the minimum-byte floor the artifact validator applied,
so a valid artifact was rejected as too small. The floor is removed; rejections now name their own
shape-based reason instead of a size.

Root Cause / Decision Record

What failed. A NIL GSTR-1 period could not be acquired at all. Three independent causes, each of which
alone was enough: the flow navigated away from the page holding the control, the control's label was
unknown to the observer layer, and a valid small artifact failed a size floor.

Why this is the smallest safe fix. Each cause is corrected where the fact belongs — the descriptor owns
control labels, the endpoint map owns surfaces, the validator owns shape. No guard is weakened: the size
floor is replaced by a shape check, which is strictly more specific than a byte count.

The fingerprint. A background handler failure rendered one generic sentence for every cause, and three
live sessions were spent guessing which throw it was. It now appends the error name and the first
non-extension stack symbol. Redaction is the point of the charset filter: only name-shaped characters
survive, so no message, path, URL or portal value can reach the panel through it.

A reduction pass, in its own commit. The diagnostics module's comment claimed emitters and the
durable allowlist read one list. They did not — emitters wrote string literals and only the
allowlist imported it, so the coupling described in the comment existed nowhere. Emitters now
declare they return one of the listed signals, which makes an unregistered literal a compile
error
rather than a runtime rejection of the whole durable array. Mutation-checked: emitting
json-parse-exploded fails the build.

The same pass found five structures across three modules holding the two portal refusals — a signal
set, a reason set, a map between them, and two allowlist entries — with the artifact- prefix that
relates them stated nowhere. One list and one derivation now. Mutation-checked: dropping a member
from the list fails a consumer test, so the derivation is real rather than decorative.

Closes no review threads; opened fresh.

Scope

  • Runtime: GSTR-1 descriptors, portal artifact endpoints, artifact validation and source classification, acquisition diagnostics, detail navigation, observer signals, download trigger, background failure fingerprint. Plus a reduction pass over the diagnostic lists (below).
  • Tests: Artifact validation and source, GSTR-1 acquisition flow, download-trigger acquisition, fingerprint redaction.
  • Docs/governance: None in this PR.
  • Explicitly out of scope: GSTR-2B behaviour, fiscal-year run state, and anything touching the ZIP — all in the PRs stacked on this one.

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

Target binding unchanged. The size floor removed from artifact validation is replaced by a shape check, which is strictly more specific than a byte count, so nothing is weakened. The failure fingerprint is the one new value that reaches a user-visible surface: its charset filter admits only name-shaped characters, and tests/background/background-failure-fingerprint.test.ts asserts a GSTIN, its digits and a URL are all absent from the output.

  • 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

No release artifact in this PR; it ships no ZIP and changes no release metadata.
Verification above was run on this branch in an isolated worktree, so the result is the branch's own and not
the stack tip's.

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
accepted / fixed / outdated / follow-up

Screenshots

Use synthetic data only.

… offers

The filed GSTR-1 detail route can carry the download control itself, labelled DOWNLOAD FILED (PDF), with no View Summary control on the page. Navigating away from a page that already offered the download left the flow waiting until its step limit.

Observer signals now read their control patterns from the return descriptors instead of restating them, so a label the descriptor learns about cannot stay unrecognised in the other layer.

A live NIL GSTR-1 summary envelope is smaller than the minimum byte floor the validator applied, so a valid artifact was rejected as too small. The floor is removed and rejections name their own shape-based reason.
…rows

A handler failure rendered one generic sentence for every cause, so three live sessions were spent guessing which throw it was. The fingerprint appends the error name and the first non-extension stack symbol, which is enough to identify the throw from the panel without DevTools.

Redaction is the point of the charset filter: only name-shaped characters survive, so no message, path, URL, or portal value can reach the panel through it.
The diagnostics module claimed emitters and the durable allowlist read one list. They did not: emitters wrote string literals and only the allowlist imported it, so the coupling the comment described existed nowhere. An unregistered signal rejects the whole durable array, which is how a diagnostic built to explain a failure halted the run instead.

Emitters now declare they return one of the listed signals, so a literal nobody registered fails to compile rather than failing at persistence. That is the level this class needs.

Separately, five structures across three modules held the two portal refusals -- a signal set, a reason set, a map between them, and two allowlist entries -- with the artifact- prefix relating them stated nowhere. One list and one derivation now, so registering a third refusal is a single line.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 11, 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-12T00:01:43.786543Z 9beb1ab New commits
ℹ️ 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: babcedc25b

ℹ️ 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/entrypoints/background.ts Outdated
Comment thread src/connectors/gst/filed-returns-durable-signals.ts Outdated
Comment thread src/background/background-failure-fingerprint.ts Outdated
Comment thread src/background/filed-returns-download-trigger.ts
Comment thread src/background/filed-returns-download-trigger.ts Outdated
Comment thread src/background/filed-returns-download-trigger.ts Outdated
Comment thread src/connectors/gst/portal-artifact-endpoints.ts
Comment thread src/connectors/gst/artifact-validation.ts
Comment thread src/connectors/gst/filed-returns-detail-navigation.ts Outdated
Three places treated "the console is not persisted" as a reason to log
whatever arrived, and one treated a character class as proof a value was safe.

**The background handler logged the raw error.** A rejection from storage,
scripting, or downloads can quote a URL, a path, or a response body. The
fingerprint carries what a reader needs and is established to be this bundle's
own, so it is what gets logged.

**The durable-signal boundary named the token it rejected.** That boundary
exists precisely because it cannot know what it has been handed -- a legacy or
malformed entry read back from storage is the input it is there to refuse -- so
repeating it in a console sink undoes the refusal. The diagnostic it replaced
was written when an unregistered signal could only be found at runtime; it no
longer can, because the signal lists are types and a producer emitting an
unregistered token fails to compile.

**The fingerprint laundered its input.** `safeSymbol` stripped punctuation, so
a stack frame pointing at a portal URL came back looking like a symbol
precisely because the characters that would have exposed it were deleted. A
filter that edits its input until it passes is worse than no filter: it
manufactures the appearance of safety.

A symbol is this bundle's because the frame it came from points at this
bundle's own origin -- provenance, not shape. A name is kept when it is shaped
like an error class, which every class here and in the platform is, and which
cannot spell a GSTIN, an ARN, or a URL. Anything else degrades to `Error`.
**A declined dialog was not bound to the target that raised it.** The detail
route does not change per period, so a dialog left standing by an earlier
target would mark this artifact unavailable -- and a composite or full-year run
would carry on having silently omitted an artifact the portal never declined
for it. The guard that binds a download click already asks exactly the right
question, so it is asked here too: recording a refusal resolves a target
outright and no artifact follows to corroborate it, which is the same bar.

**A View Summary step was skipped on a text-derived signal.**
`download-filed-gstr-1` says the filed-PDF label appears somewhere on the page,
which decoy or non-actionable copy also does. Skipping the real control on that
basis strands a target whose PDF was reachable: acquisition then finds nothing
to click and blocks it. Whether a page offers an artifact is a question about
controls, so the page's controls are what get asked.

The resolver that answers it moves next to the descriptor owning the label, so
the two cannot drift apart, and `artifact-source` loses its private copy.
**Inspection failure replaced the acquisition failure.** The follow-up message
runs after an acquisition has already failed and can only refine it. A tab that
has closed, navigated, or refuses injection means the failure cannot be
refined, not that a new one occurred -- but the unguarded call threw, replacing
a specific actionable reason with the generic background error and losing the
terminal summary with it.

**A definitive refusal left its intent checkpoint standing.** The retain
decision is made about an acquisition failure. When the portal's no-details
answer replaces that failure, it is no longer one: nothing exists to download,
so nothing is left for a retry to reconcile. The checkpoint survived anyway and
blocked the next attempt as `artifact-acquisition-start-unreconciled` --
refusing the retry that very result offers.

The nested ternary became an early return; the second fix has nowhere to live
inside an expression.
The size cap is a processing bound, not only a verdict. A rejected oversized
preflight body went straight into the diagnostic helper, which decoded and
parsed all of it -- spending exactly the work the cap exists to refuse, on the
one path where the input is known to be unreasonable.

The band is the whole diagnostic here: nothing inside an oversized body would
change what a reader does about it. The signal registers by derivation, so no
allowlist needed telling.
Each fails with its guard removed.

The fingerprint fixtures used invented `file.js` frames. A background stack
points at this bundle's own origin on every line, which is what makes a symbol
ours -- so a fixture that omitted it could not have caught a frame from
anywhere else.
The change relied on a live 2026-09-10 capture that this repository had not
recorded, while `LIVE_FILED_RETURNS_SPIKE.md` still stated the opposite from an
earlier one: that the detail page never exposes the PDF and must be navigated
through View Summary. Both captures are real. The detail route has two shapes,
and the spike's paragraph was read as a general rule.

A contradiction left standing is how a fix gets reimplemented from the stale
half, so the spike entry is marked superseded in place -- it stays, because it
is a dated record of what was seen -- and the finding goes where captures go.

@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: 9beb1aba59

ℹ️ 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/portal-artifact-endpoints.ts
Comment thread src/background/filed-returns-download-trigger.ts
Comment thread src/background/filed-returns-download-trigger.ts
Comment thread src/connectors/gst/artifact-source.ts
Comment thread src/connectors/gst/artifact-validation.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