Skip to content

chore(audit): workflow-timeout + override-parity guardrails, OAuth state hardening - #114

Merged
agjs merged 3 commits into
mainfrom
chore/audit-fixes-20260602-1643
Jun 2, 2026
Merged

chore(audit): workflow-timeout + override-parity guardrails, OAuth state hardening#114
agjs merged 3 commits into
mainfrom
chore/audit-fixes-20260602-1643

Conversation

@agjs

@agjs agjs commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Executes all 3 findings from today's monorepo audit on one branch. Guardrail-first: 2 of 3 fixes ship as new lint-meta rules that surfaced (and now block) the whole defect class — the rules found 3 more real instances than the audit itself.

F001 — fix(ci): workflow jobs must declare timeout-minutes (7b62f8c)

  • New github-actions-timeout-required lint-meta rule in both apps (jobs without a timeout run to GitHub's 6h default and block PR checks; reusable-workflow calls exempt).
  • Workflow discovery now walks up to the repo-root .github/workflows — per-app lint-meta looked for <app>/.github/workflows, which doesn't exist in the monorepo layout, so the existing github-actions-permissions rule (SHA pins + permissions blocks) was silently scanning an empty set. It now actually enforces against all 23 workflows. Standalone split-out repos are unaffected (the fallback never triggers).
  • Fixes the two jobs the rule surfaced: apps-docs-linkcheck (20m) and infra-bootstrap-validate (10m).

F002 — fix(deps): security-override parity across apps (bf69ffa)

  • New package-override-parity lint-meta rule (api, supply-chain): an app's overrides must be reflected in its own bun.lock and mirrored by sibling apps that resolve the same package.
  • The rule surfaced three real instances (the audit had found one):
    • ui resolved ws@8.20.1/7.5.10 with no mirror of the docs ws@8.21.0 pin (GHSA-58qx-3vcg-4xpx) → mirrored.
    • ui resolved qs@6.15.1 with no mirror of the docs qs@6.15.2 pin (GHSA-q8mj-m7cp-5q26) → mirrored.
    • docs' bun.lock resolved @types/react@19.2.14 despite its own 19.2.15 override (stale resolution) → re-resolved.
  • Note: the ws pin forces lighthouse's exact ws@7.5.10 up to 8.21.0 — security over local-only dev tooling; docs made the identical call. Revisit if bun run lighthouse regresses.

F003 — fix(api): reject malformed OAuth state (2666bfe)

  • oauthStateStore.consume() returned {} when the stored Valkey value failed JSON.parse or wasn't an object — indistinguishable from a legitimately stored empty state. Corrupted state now routes through the same null rejection path as forged/expired state (→ 401).
  • Adds the missing oauth.state.test.ts (round-trip, replay burn, garbage, JSON scalar, unknown-field stripping).

Audit decisions log: .audit/execution-summary.json (gitignored, local). The report's 7 blocked_or_uncertain items were skipped by design (they need evidence/maintainer decisions, not code).

Test plan

  • bun run check green in apps/api and apps/ui; bun run check:docs-data green in apps/docs
  • Full api suite: 1069 tests / 1365 expects, 0 fail (includes 5 new oauth.state tests, 5 new lint-meta rule tests)
  • RED→GREEN proven for both new rules: each flagged the exact known instances before the fix, zero violations after
  • Pre-push gate (security, docs, root fan-out) passed on push
  • Stack smoke not run — no compose/infra runtime changes (workflow YAML only)

Conventions

  • No any, no blind as, no !
  • No new env vars (schema/.env.example untouched)
  • Tests updated for changed behavior (new rule tests in both apps + oauth.state.test.ts)

Screenshots

n/a — CI/lint-meta/API-internal changes only.

agjs added 3 commits June 2, 2026 16:54
New github-actions-timeout-required rule in both apps' lint-meta; workflow
discovery now walks up to the repo root .github/workflows in the monorepo
layout, un-orphaning github-actions-permissions which silently scanned an
empty set. Adds the two missing job timeouts the rule surfaced
(apps-docs-linkcheck, infra-bootstrap-validate).

Audit: F001
…ity rule

New package-override-parity lint-meta rule: an app's overrides must be
reflected in its own bun.lock and mirrored by sibling apps that resolve
the same package. Surfaced three real instances: ui missing ws@8.21.0
(GHSA-58qx-3vcg-4xpx) and qs@6.15.2 (GHSA-q8mj-m7cp-5q26) mirrors of the
docs pins, and docs' bun.lock resolving @types/react@19.2.14 despite its
19.2.15 override. Also regenerates the docs lint-meta catalog for this
rule and github-actions-timeout-required.

Audit: F002
consume() returned {} when the stored Valkey value failed JSON.parse or
was not an object — indistinguishable from a legitimately stored empty
state. Corrupted state now routes through the same null rejection path
as absent/forged state. Adds the missing oauth.state.test.ts covering
round-trip, replay burn, garbage, scalar, and unknown-field stripping.

Audit: F003
@agjs agjs changed the title Chore/audit fixes 20260602 1643 chore(audit): workflow-timeout + override-parity guardrails, OAuth state hardening Jun 2, 2026
@agjs
agjs merged commit 3c7535b into main Jun 2, 2026
28 checks passed
@agjs
agjs deleted the chore/audit-fixes-20260602-1643 branch June 2, 2026 16:36
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