feat/one-api
needs attentionviewing older commit29d19a0 · incrementalpre-PRreviewed 2026-08-11 17:41 UTC1H · 5M · 9L · 1I- Purpose
- Harden the one-API surface: RLS isolation, machine-caller isolation, cross-org leak prevention, entity_relationships removal, service keys, utility-contracts API, telemetry.
- Goal
- Close all known security and correctness gaps before shipping feat/one-api to main. 50+ commits across 15+ rounds of review.
- Sub-goals
- SG-1: RLS isolation for all reads and writes
- SG-2: Machine-caller (service key) isolation
- SG-3: entity_relationships table and path removal (BAT-301)
- SG-4: Utility-contracts API revival + CI gating
- SG-5: Ratified design decisions documented (BAT-298, DROP POLICY)
- What
- Revived utility-contracts API integration suite (stale JWT re-login, vacuous search fix, sitePublicId assertion), wired suite into CI, ratified no-proof RPU claiming and bare-DROP-POLICY decisions.
- Why
- Suite was silently broken since JWT moved to claims-driven (BAT-135). Two design decisions needed CTO ratification to stop review panels re-flagging them.
- Areas
- apps/platform+4547−4130domains/core+1382−3342packages/api+681−1380packages/database+1000−351domains/cross-domain+720−299.claude/rules+604−33domains/utility+237−335scripts/one-api+78−303
- Blast
- 245 files, +10851/-10676 across the full branch. Incremental this commit: 6 files, +98/-27.
Findings · 16
correctness2
testContractRpu undefined if first test fails — TypeError masks root cause
apps/platform/src/__tests__/integration/utility-contracts-api.test.ts:364
Same as tests/high but noted from correctness angle — the crash is a TypeError from undefined.slice, not a test assertion failure, hiding the real issue.
eval silent-succeeds if supabase status returns non-JSON — ANON_KEY left unset
.github/workflows/pr-checks.yml:437
If supabase status returns non-JSON, python3 exits nonzero but eval of empty string succeeds. Add set -euo pipefail at top of run block.
security1
Ephemeral keys visible under ACTIONS_STEP_DEBUG — add ::add-mask::
.github/workflows/pr-checks.yml:437
Keys are localhost-only; masking is standard hygiene. Add echo '::add-mask::$SUPABASE_SERVICE_ROLE_KEY' after eval.
conventions3
Pervasive 'what' comments in test setup (pre-existing)
apps/platform/src/__tests__/integration/utility-contracts-api.test.ts:21
Many comments describe what the code does rather than why. Convention: one short WHY line max.
New multi-line comment blocks in two test cases exceed one-line rule
apps/platform/src/__tests__/integration/utility-contracts-api.test.ts:212
5-line and 3-line blocks in the new/renamed tests. Compress to one line each.
Test naming mix: 'should X' vs behavior-first in same file
apps/platform/src/__tests__/integration/utility-contracts-api.test.ts:173
Pre-existing debt — corrected test sets the right pattern but siblings are not aligned.
tests5
testContractRpu ordering dependency — undefined.slice throws TypeError on skip/fail
apps/platform/src/__tests__/integration/utility-contracts-api.test.ts:364
testContractRpu is assigned in 'should create contract with site info' and used unguarded in 'should search by RPU'. If first test is skipped or fails, .slice(0,8) throws TypeError masking the root cause. Guard: if (!testContractRpu) throw new Error('Prerequisite test did not run').
isMonitored filter test passes vacuously on empty result set
apps/platform/src/__tests__/integration/utility-contracts-api.test.ts:357
Array.every() returns true for []. If creation test failed, the assertion still passes. Add: expect(matched.length).toBeGreaterThan(0).
Cloud getTestUserToken fast path bypasses custom_access_token_hook — membership claims missing if userId ever passed
apps/platform/src/__tests__/helpers/supabase-helpers.ts:170
Current call (no userId) is correct for local CI. If CI switches to cloud Supabase, the re-login mints a hook-free JWT and every membership-gated handler silently 401s, regressing to pre-fix state.
Duplicate RPU test orphans a site + contract in shared DB
apps/platform/src/__tests__/integration/utility-contracts-api.test.ts:264
First successful contract in duplicate-RPU test never tracked for cleanup — leaks into shared test DB.
No negative test pinning stale-token rejection
apps/platform/src/__tests__/integration/utility-contracts-api.test.ts:134
Root cause (pre-org token rejected) only documented by comment; a failing negative test would prevent future regression.
improvement5
Replace python3 key-extraction with jq (already on runner)
.github/workflows/pr-checks.yml:437
jq is on ubuntu-latest. Simpler: eval "$(supabase status --output json | jq -r '\"export NEXT_PUBLIC_SUPABASE_ANON_KEY=\" + .ANON_KEY, \"export SUPABASE_SERVICE_ROLE_KEY=\" + .SERVICE_ROLE_KEY')"
Pass owner.user.id on re-login to avoid redundant GoTrue round-trip
apps/platform/src/__tests__/integration/utility-contracts-api.test.ts:133
getTestUserToken(owner.email, owner.password, owner.user.id) skips signInWithPassword on local fast path. Consider a refreshTokenForUser(user) helper for reuse across suites.
Search term slice(0,8) causes all test-run contracts to match — assertion weaker than it appears
apps/platform/src/__tests__/integration/utility-contracts-api.test.ts:364
All Date.now()-based RPUs share first 8 digits. Use testContractRpu.slice(-6) or full RPU for a unique match.
URL query string in search test is unused by direct handler call
apps/platform/src/__tests__/integration/utility-contracts-api.test.ts:367
Handler reads from args.query; the url: query string is ignored. Remove or document.
NEXT_PUBLIC_SUPABASE_ANON_KEY should be in env: block for auditability
.github/workflows/pr-checks.yml:445
Sibling steps declare it in env:. This step sets it via eval side-effect — asymmetric.
History · 47 commits
- 82bb5b9blockedincremental5H · 5M · 4L2026-08-12 01:48
- 90aa3d5needs attentionincremental1H · 5M · 3L2026-08-11 19:37
- 29d19a0needs attentionincremental1H · 5M · 9L2026-08-11 17:41current
- 9bd8a0cneeds attentionfull0H · 5M · 9L2026-08-11 02:14
- 62ec3f7needs attentionincremental2H · 5M · 6L2026-08-10 22:51
- f93bca9needs attentionincremental2H · 5M · 8L2026-08-10 17:51
- 052db6fneeds attentionincremental1H · 3M · 4L2026-08-09 21:13
- 45699caneeds attentionincremental0H · 7M · 11L2026-08-09 17:44
- b843d8aneeds attentionincremental1H · 7M · 9L2026-08-09 04:05
- e1757b8needs attentionincremental0H · 3M · 6L2026-08-05 02:11
- 7a762faneeds attentionincremental2H · 5M · 5L2026-08-05 01:25
- 3300a60needs attentionincremental2H · 4M · 7L2026-08-04 19:06
- 0c8a7f5needs attentionincremental0H · 4M · 9L2026-08-04 18:15
- 345f42eneeds attentionincremental2H · 6M · 9L2026-08-04 17:28
- 8338a9aneeds attentionincremental5H · 14M · 14L2026-08-04 00:33
- 41be4c3needs attentionincremental0H · 5M · 7L2026-08-03 23:49
- 5ed593dneeds attentionincremental1H · 6M · 6L2026-08-03 21:32
- b333e25needs attentionincremental4H · 9M · 8L2026-08-03 21:00
- 5642cccneeds attentionincremental2H · 3M · 2L2026-08-03 20:17
- 73b0b39needs attentionincremental3H · 10M · 13L2026-07-31 18:29
- b19852eneeds attentionincremental0H · 1M · 5L2026-07-29 05:04
- 3845205needs attentionincremental3H · 6M · 4L2026-07-29 04:47
- eb8eb50needs attentionincremental0H · 1M · 2L2026-07-29 03:03
- f4720a3needs attentionincremental6H · 8M · 7L2026-07-29 02:54
- f8d341ablockedincremental2H · 2M · 5L2026-07-29 00:00
- a7f1a64needs attentionincremental2H · 8M · 8L2026-07-28 18:41
- 738b60bblockedincremental3H · 6M · 5L2026-07-28 00:46
- 2c248b6needs attentionincremental8H · 12M · 8L2026-07-27 23:23
- 1346cc0needs attentionincremental2H · 8M · 6L2026-07-27 20:15
- 0716018needs attentionincremental2H · 11M · 12L2026-07-27 19:22
- 215cd2dneeds attentionincremental3H · 6M · 5L2026-07-27 17:04
- ec46958needs attentionincremental0H · 3M · 5L2026-07-27 16:51
- de7b337blockedincremental4H · 9M · 14L2026-07-27 06:36
- b1bb9c0needs attentionincremental1H · 2M · 4L2026-07-27 05:09
- 4701d11needs attentionincremental0H · 4M · 3L2026-07-27 04:44
- e1626c4needs attentionincremental3H · 9M · 10L2026-07-27 03:21
- 195f198needs attentionincremental3H · 3M · 3L2026-07-25 01:22
- 42c7358safeincremental0H · 0M · 0L2026-07-22 20:46
- 85b9018needs attentionincremental0H · 1M · 6L2026-07-21 23:51
- a7b2a9aneeds attentionincremental0H · 9M · 12L2026-07-21 18:49
- c2ee0daneeds attentionincremental4H · 7M · 7L2026-07-21 02:17
- e8ffa5eneeds attentionincremental4H · 7M · 5L2026-07-21 01:33
- a2d2a54needs attentionincremental2H · 7M · 3L2026-07-21 00:51
- 576fbd6needs attentionfull1H · 6M · 7L2026-07-21 00:35
- d3465e8needs attentionincremental1H · 7M · 10L2026-07-21 00:23
- dc794a7needs attentionincremental0H · 5M · 5L2026-07-20 23:46
- 9082773needs attentionfull1H · 3M · 3L2026-07-20 23:13