Skip to content

chore: promote staging 3.6.0 (audit remediation, PRs #173-#186) to main - #187

Merged
lnieuwenhuis merged 86 commits into
mainfrom
staging
Sep 17, 2026
Merged

lnieuwenhuis merged 86 commits into
mainfrom
staging

Conversation

@lnieuwenhuis

Copy link
Copy Markdown
Owner

Summary

Promotes verified staging (app version 3.6.0) to main: the macro-tracker audit remediation — 71/71 accepted findings across 12 topic PRs plus 2 test-harness follow-ups.

Verification

  • Closeout verification on this exact tree: staging tip 2582e61e (merge of PR test(web): isolate startup fixtures from inherited npm_execpath casing #186). #185/#186 deltas are test-only (apps/backend/src/legacy_api/tests/mod.rs, apps/web/tests/unit/startup-process.test.ts); no non-test file changed after 75a22858, so app-content equivalence holds from the fully re-gated tree to the tip.
  • Local gate at the final tree: cargo 237/237; web vitest full default order 574 passed / 2 POSIX skips / 0 failed; db 128; e2e 33; typecheck, lint, build, audit:code green; gitleaks over 7a354d9d..2582e61e clean.
  • Staging Railway: web b82835ad SUCCESS @ 2582e61e; backend c8f8643b SUCCESS @ 5a408619 serving; Postgres RUNNING; /login 200.
  • This PR's fresh CI run (7/7) is the merge gate.

Migrations

  • 0015/0016 re-selected for the staging line are now guarded (IF NOT EXISTS catalog checks) no-ops for histories that already applied them; production, which never applied them, receives them and the guarded 0019 HealthKit re-tag, each first-time statement applying exactly once.
  • Migration runner restores session timeouts after use and discards a connection whose cleanup failed; covered by db package tests and migration runner tests.
  • Additive and idempotent only; no destructive statements, no arbitrary when/tag changes.

Breaking behavior

  • None expected. API changes are additive or behavioral fixes on existing routes; version 3.6.0.

Risks

  • Production db:migrate pre-deploy is the critical step to monitor (guarded re-selection described above).
  • Benchmark food image bytes are intentionally frozen by AI-01/02; do not "fix" formatting.

OPS-02: cleanup.sh defaults to read-only discovery, requires explicit
--repo allowlist plus --apply for deletions, skips protected/default
branches, verifies merged status via compare, paginates branch listing,
and removes description clearing/branch renames.

OPS-07: entrypoint.sh escapes operator YAML scalars (backslash/quote)
in POSIX sh, validates PORT, rejects newline values without printing
secrets, and supports isolated config-path/skip-exec test hooks.

Tests: fake-gh cleanup safety suite and isolated entrypoint YAML
round-trip suite with dummy values only; never runs live cleanup.
…p tests

OPS-02 review follow-up. gh api does not parse flags embedded in the
endpoint string: the previous 'repos/.../branches --paginate --jq ...'
form requested a 404 path, so real branch listing always failed and
cleanup.sh skipped every repo (safe but non-functional). Flags are now
separate argv entries; a fake-gh argv regression test (T5) fails on the
old form. T3's protected-branch check was a no-op pipe with reversed
patterns; it now asserts no DELETE for protected/unmerged branches, and
T1 also covers --apply without --repo.
fix(ops-safety): safe cleanup pruning and YAML-escaped operator config (OPS-02, OPS-07)
AI-01: validate baseline model, fixture version/IDs, result shape and age
server-side, then reuse actual compatible current-model cases without
provider calls. Invalid/stale baselines fall back truthfully with accurate
call budgets. Same-model runs deduplicate; valid baselines make 0 calls
(same-model) or candidate-only calls.

AI-02: replace 10 random loremflickr inputs with pinned stable Commons
files so every compared model receives identical input. Record lowercase
SHA-256 of checked-in thumbnails plus attribution, expose imageUrl/hash in
fixture JSON, and version the set as 2026-09-17-pinned-v1 to invalidate
incompatible caches. Client cache moves v2->v3 and checks version/length.

Tests use stub providers with call counters; no paid gateway calls.

(cherry picked from commit 135ce6d714611e3f0f92ad52fdf0f727fb741482)
next/eslint-config-next 16.3.3, sharp 0.35.4 (libheif 1.23.2), js-yaml 4.3.2, vite 8.0.16, browserslist 4.28.7, baseline-browser-mapping 2.11.0, @humanfs/node 0.16.8, smol-toml 1.7.1. pnpm audit reports zero advisories. vite is an explicit vitest peer because pnpm 10 does not rewrite auto-installed peers from overrides.
rustls 0.23.41 -> 0.23.45 (RUSTSEC-2026-0285) and event-listener 5.4.1 -> 5.4.2 (RUSTSEC-2026-0221); rustls-webpki follows to 0.103.15 and concurrent-queue is dropped. rsa 0.9.10 remains an inactive optional MySQL match with no published fix.
…ls with keyboard support, single recipe toggle, progress goals guard
…cipe portions and ingredient guards with regressions
fix(deps): audit dependency patches DEP-01/DEP-02
UI-05: use-action-runner catches transport rejection into fallbackError/onError
without refresh; NEXT redirect/notFound still rethrow. Template save/delete/update
catch rejection (delete restores optimistic row) and return false for honest
retry. Regression: runner rejection + recovery, template save/delete/retry.
UI-02: analysis sequence guard commits estimate/question/error only for the
request/image that produced them; replacement clears analyzing state so the new
photo is actionable. Regression: held A estimate and clarification released
after B selection never appear.
UI-07: 401/403, redirected and HTML-login barcode responses return auth, with
sign-in recovery and kept-code retry in the scanner instead of a connectivity
error. UI-09: decimal-comma normalization applies to numeric fields only; the
barcode label keeps commas verbatim.
UI-08: shared shouldSuppressGlobalShortcut covers defaultPrevented events,
focus inside dialog/menu/listbox, and any open dialog/menu in the document, so
arrows on modal buttons no longer navigate the day and remount the page.
UI-22: history copy and product add use a fresh local date for each new
operation instead of the mount-memoized today; retries keep the original
date/key until settled. Search transport rejection now surfaces a local error
instead of an unhandled rejection.
UI-01: photo and barcode dialogs await the template save, show Saving and a
local error, and mark Saved only on success; resolved failures and transport
rejections keep retry. Manual barcode product save handles transport rejection
without hanging. Dashboard and recipe consumers return the save promise.
UI-03: status changes merge the server row under unsaved edits instead of
replacing the draft; same-day refreshes reconcile against the pre-refresh
baseline so unrelated cards keep dirty fields while untouched fields adopt
fresh server values. UI-25: single saving/active markers become a per-entry
pending set with a synchronous admission guard; completions and failures
release only their own card, and saves preserve edits admitted mid-flight.
UI-05: dashboard save/status/delete/group-copy/apply/group-manager paths route
transport rejection to per-card local errors with rollback. Add-to-today from
history stays intentional.
Windows pnpm trees link standalone output back into the source store with absolute junctions. Resolving through them made prepare-standalone delete the installed @swc/helpers and fail. Rebase escaping output links onto their in-artifact counterparts and refuse to replace helpers outside the standalone output. Add an absolute-junction regression fixture.
spawn('pnpm') returns ENOENT on Windows because the package manager is pnpm.CMD. Prefer the JavaScript entry from npm_execpath when present and fall back to the platform launcher, and make the process fixtures platform-portable with direct kill on Windows, path.delimiter, retried temp cleanup and no orphaned children.
The scoped apps/web config omitted railpack.json while the root fallback watches it, so a railpack-only change would not redeploy a service using the scoped config. Add the shared watch path and a parity test for shared build inputs and representative changed paths.
MIG-01: 0016's unconditional ADD CONSTRAINT raises 42710 when a database that applied the pre-unification 0015/0016 history is upgraded under the reunified journal, rolling back every pending migration. Guard each ADD CONSTRAINT behind a pg_constraint check so the re-selected migration is a strict no-op there, leave the deployed journal identities untouched, and record the reunified-history rule in MIGRATIONS.md.

TEST-02: migrateDatabase left session-level lock_timeout and statement_timeout on the pooled connection, so a later checkout of the migrated connection could fail a lock wait after three seconds. Capture the previous settings, restore them in a finally (including after a failed migration), and destroy the connection instead of reusing it when cleanup itself fails.

Regressions: historical upgrade fixtures through the real migrator (clean, pre-unification through 0016 and through 0018, production HealthKit applied as 0015) plus timeout restoration, controlled lock-wait and failed-migration cleanup tests in packages/db/tests/migration.test.ts.
(cherry picked from commit 5d434148a4444636c62673c280bc16aaacb122b3)
fix(benchmark): verified frozen fixture inputs and truthful baseline reuse (AI-01, AI-02)
fix(audit-ui-controls): validated UI controls release (UI-06/10/16/17/20/21/28/29)
fix(db): preserve historical migration upgrades, restore session timeouts, pin fixture parity (MIG-01, TEST-01, TEST-02)
fix: data integrity and persistence locks (DATA-01..17, API-05, SEC-06)
…rk179) into fix/audit-ui-display-staging; preserve controls tabs/validity with display year labels
…-staging

Integrate DATA (#184) after controls (#183), migrations (#180), security (#178), build (#175) and benchmark (#179). Semantic resolution: keep DATA's BrowserFoodProduct types together with the UI-22 per-operation date/idempotency-key logic in food-search-modal.tsx (drop the mount-memoized todayStr/useMemo); all other overlaps auto-merged, including the promise-returning onSaveAsPreset against the controls recipe-builder changes. Preserves controls, security, benchmark and DATA/API-05 patch semantics alongside UI-03 client dirty-draft merging.
Merge resolution for pagination + DATA184: stats_page_data_json now returns StatsPageData (data + window counts) for pagination metadata. Update data_integrity zero-calorie test to read stats.data. No DATA logic changed; pagination metadata still derives from daily.
fix(audit-contracts): API-02/API-03/OPS-04/OPS-05 contracts review (HOLD MERGE pending DATA-03)
…-staging

Integrate contracts (#177) after DATA (#184); no file overlap with this seat (api-v1/openapi/docs/packages-db types only).
…ion-staging

# Conflicts:
#	apps/web/lib/api-v1-openapi.ts
#	apps/web/tests/unit/openapi-parity.test.ts
fix(ui): audit mutation-state fixes UI-01/02/03/05/07/08/09/22/25
…i-display-staging; preserve display validation/hour/year with state dirty/SEC-06
feat(api): opt-in cursor pagination and truncation metadata (API-01), 3.6.0
fix(audit): UI display recovery (UI-04 UI-11 UI-12 UI-13 UI-14 UI-15 UI-18 UI-19 UI-23 UI-24 UI-26 UI-27)
…oisoning

tracing-core caches Interest per callsite process-wide. While at most one dispatcher has ever been registered, a first hit is resolved from the registering thread's default subscriber, so a parallel no-subscriber test thread could cache Interest::never for upstream_photo_failure and silently drop the captured warn events (SEC-04 flake). Register one permanent no-op dispatcher so the registry stays on the multi-dispatcher path. Add an isolated deterministic regression that fails without it.
…staging

test(backend): stabilize SEC-04 log captures against tracing callsite-interest races
pnpm script invocations on Windows expose npm_execpath as NPM_EXECPATH. The fixture's exact-case delete left the inherited key in the child environment, so the launcher used the real pnpm instead of the fixture shim/entry: migrations exited 0 without writing the marker and the exit-7 gate served anyway. Remove every case variant before the runner is selected and cover both runner modes with a regression that restores the inherited value.
…ation

test(web): isolate startup fixtures from inherited npm_execpath casing
@lnieuwenhuis
lnieuwenhuis merged commit 63e907f into main Sep 17, 2026
10 checks passed

This branch was previously deployed

1 inactive deployment
macro-tracker / staging — 2582e61e Deployed Sep 17, 2026 by railway-app[bot]
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