Skip to content

Venue ownership pipeline implementation audit

Status: Active Last reviewed: 2026-09-07 Scope: V4 server ownership, existing venue permissions, shared contracts, account export, private app workflows and current certification display.

Plan and research

The accepted plan separates community information reliability from ownership authority. The server uses an application/event/request ledger and explicit tenures; the app uses the same strict entity, wire and request contracts. It reuses the correction/contribution engine, account lifecycle, signal mechanism and account-export entry point.

Research read the current migration definitions, consumers and prior role/roster tests, then checked PostgreSQL's explicit locking and SELECT locking behavior. The pinned runtime rehearsal follows Supabase's main-worker dispatch example. No provider response shape, successful account mutation or deployment was inferred from mock behavior alone.

The implementation is eight migrations, thirteen public RPCs, three domain entities, wire/request builders and four Edge export modules. The workflow specifies product behavior, privacy, retries, transfer consent and resource bounds. Root integrates and executes the combined gates; separate authors and reviewers examine SQL, export and app contracts.

Independent findings and repairs

  • A role gained after the authorization prefix could have been re-read later and promoted a legacy pending correction into an instant write. Captured role tiers now govern the entire operation, with real two-session grant/removal checks.
  • Deferred projection constraints ran after a definer RPC returned to authenticated, and failed on sealed raw tables at transaction completion. The narrow constraint guard is now SECURITY DEFINER with an empty search path and revoked direct execution. Tests force constraints while still authenticated and use actual HTTP commits.
  • After that incidental permission failure was removed, the legacy closure path exposed protected reopening. The parent-locked guard now preserves merged and not-a-venue restrictions and rejects reopening a row with a successor for every role.
  • Active-account checks now include Auth soft deletion. Profile/Auth lock ordering, immediate tenure ending and post-wait rechecks prevent stale JWT authority; restoring account rows cannot revive prior tenures. Reviewer anonymization preserves other owners.
  • Redaction timestamps reject nonfinite, future and backward values. Request tombstones remain digest-free and actor-free while preventing recycled request UUIDs.
  • The export's inherited profile table query failed under current column privileges; it now uses get_own_profile(). Actual pinned SDK/PostgREST execution also found nonexistent authored-post columns; aliases preserve the existing JSON field names while reading canonical body/type and excluding other authors.
  • Historical venue test fixtures now import their complete legacy grants explicitly. Revocation tests call the exact-tenure API instead of erasing a historical reviewer. Invalid original pairs remain inactive after raw-field repair. The anonymous ACL exception is limited to the exact no-personal-data certification projection.

Evidence at integration

The final draft SQL passed 285 assertions across eleven suites, including authenticated constraint completion, scope, exact replay, consent, transfer, legacy reopening, private history, departure, import and bounded anonymization. Two-session tests passed fifteen role-race checks and nine account-deletion checks with actual database blocking barriers. Eighteen existing venue suites passed 1,079 assertions after the necessary fixture updates.

All 100 canonical Node contract/export tests pass on Node 22.22.0 and 20.20.2: 61 shared contract checks and 39 export checks, including independently authored privacy, pagination and resource-boundary probes. Strict app/Edge TypeScript and full ESLint pass. The repository yarn check passes with 5,593 Jest tests across 389 suites and 562 script tests: 560 pass and two existing environment-gated tests remain skipped.

The broader canonical SQL matrix passes all 53 venue/court/ACL suites and 1,823 assertions. The ACL regression proves that PUBLIC execution and a same-name overload remain violations. Four numbered historical suites retain their 77 original assertions and add five import/ stable-roster checks. A separate retained database applied all 26 migrations 0060300628 with a separate commit per file, importing one valid historical tenure and inventorying one invalid grant without changing venue facts. Its public/private function definitions, signatures, search paths and ACLs match the reviewed schema.

The real local Edge Runtime 1.74.0 and pinned supabase-js 2.98.0 rehearsal passed 29 HTTP checks. PostgREST 14.4 verified JWTs and exercised actual SQL permissions and committed submit/replay/review/relinquish transactions. Export exhausted eleven own claims and 46 events: 36 application events and ten imported legacy events. Other users' evidence and posts stayed excluded; account deletion before the final check returned no partial data. Independent mapping checked those committed wire receipts through the app contracts.

The Auth /user endpoint in that rehearsal was an explicit synthetic fixture. The schema-only database lacks the complete GoTrue migration history; this does not establish full GoTrue integration. All data was synthetic. Test-only service authority stayed in the dispatcher used to trigger account departure, never in the candidate user worker. Named rehearsal containers were stopped; isolated databases and ignored receipts remain.

Database types were generated by local postgres-meta 0.96.6 from the final schema. Only three public table members and thirteen RPC members differ; the synthetic template's missing managed GraphQL schema did not remove the existing GraphQL type declarations. The generation source and before/after hashes are retained with the promotion manifest.

Local evidence lives under .audit/venue-pipeline-v4-20260906/: sql-rehearsal/, sql-implementation-review/, export-rehearsal/, export-implementation-review/, sql-regression-review/ and backend-promotion/. Canonical regression fixtures are in supabase/tests/ and scripts/__tests__/; none imports ignored draft code or logs.

App request and cache foundation

The integrated client adds thirteen repository operations, a cancellable six-slot transport shared with the existing Supabase client, and an account-scope provider in both platform shells. Private operations capture a current auth-port session per attempt and recheck it immediately before dispatch. Public certification calls have an explicit scope without private actor authority. Query and mutation caches clear on scope changes; private owner roots cannot persist or hydrate. Response checks preserve immutable venue, request, kind, replacement and outgoing-tenure bindings while permitting replay receipts to reflect later authorized decisions.

Research traced the installed Supabase auth callback/session behavior, the real auth adapter's expiry units, TanStack's query lifecycle and the existing storage hash. React's ref guidance and layout-effect semantics informed the committed-lifetime boundary. Independent review reproduced and repaired these failures:

  • The auth port exposes milliseconds, while raw JWT expiry uses seconds. A second conversion could dispatch an expired token after queueing; the final check now uses the port's actual units, including a real adapter/SDK regression.
  • A delayed SDK INITIAL_SESSION for a previous account could strand explicit retries. A fresh retry now reads the current session, while newer auth events still supersede that read and old request leases remain invalid.
  • Writing account refs during render allowed an abandoned suspended render to poison the committed account lifetime. Only committed layout effects now change those refs. Tests cover abandoned renders, actual account transitions and child layout requests.
  • Two different query keys can share the existing 32-bit storage hash. Hydration now checks the stored key, denies owner roots and requires an exact requested-key match; ordinary allowed persistence and hydration remain covered.
  • Mutation and context receipts now reject incompatible immutable request bindings. Own-claim listing rejects a receipt without the caller's own-read entitlement.

All 66 canonical client tests pass: 28 author checks, nineteen independent lifecycle, transport and persistence probes, and nineteen independent repository/SQL-wire contract checks. They execute canonical modules and the installed SDK rather than ignored drafts. A separate narrow probe against private hooks was retained for their later promotion; it was not counted in this foundation's canonical acceptance. Full client integration, promotion mapping and repository checks are recorded separately from server rehearsals under app-client-promotion/ and app-client-promotion-review/ in the ignored audit folder.

Transport deadlines retain the existing behavior: twenty seconds for REST and 150 seconds for Edge dispatch, ending at response headers. Caller cancellation remains connected while the SDK reads the body. This slice does not introduce a new response-body duration or byte limit for every existing app request.

Private workflow and certification integration

The next app slice integrates private query/history/mutation hooks, application and review screens, both platform route shells, ownership signal navigation and current certification at every badge consumer. Independent preparation and canonical comparison check all 84 runtime targets against accepted source bytes and declared import changes. The previously deferred provider/private-hook companion is now a permanent regression.

Research traced React's committed effects, TanStack's actual observer/fetch behavior, the installed SDK and canonical auth port. The club viewport uses the existing UI measurement convention, informed by React Native's ScrollView events and React Native Web's View measurement methods. The private evidence workflow remains separate from public venue fact reliability.

Independent review reproduced and repaired these failures before integration:

  • Session-read failures could leave explicit retries unavailable. A new current-session retry now recovers without reviving an earlier account's request lifetime.
  • A forbidden history refresh could leave old full-receipt actions visible. The whole private receipt now stays hidden until a successful authorized detail refresh.
  • Retained URL and navigation callbacks could outlive their receipt. They now recheck current receipt/context identity, and interrupted-denial state resets with that boundary.
  • Two observers sharing a failed certification request could repeatedly schedule each other; the reproduction dispatched 22 requests in ten seconds. Observers now join the actual current request, including synchronous fetch notifications. Shared failure stops, and an explicit retry recovers both observers with one request.
  • Large club selections stopped checking after the first thirty courts. Measured viewport subscriptions now advance the bounded batch without limiting the user's selections. Reactivation also replays viewport changes made while the search overlay was open.
  • Full-project lint reached feature-path rules that draft-only lint had missed. Ownership rows now use a flat layout with an underlined receipt link, read states use local spacing, and history/transfer lists retain stable key callbacks. The four-file amendment preserves authorization and navigation guards and has its own independent review and regression run.

Canonical test promotion preserves 60 private-flow cases, 43 certification/core cases, 17 route/signal cases, two actual private-mutation/public-proof interaction cases and ten actual consumer/viewport cases. The interaction tests use the real private action cache, public proof cache and SDK transport in one runtime. They prove affected proof suppression, fresh settlement checks and isolation of an old account's completion from the new account. Consumer Jest verification covers 299 cases across 25 suites, including draft persistence, canonical adopted IDs, focus, overlay transitions and 31/101-court scrolling.

The first canonical test promotion found a fixture import still pointing to the earlier mapper directory; only that fixture path changed. A separate route denial fixture was corrected to use the SQL's actual constant error hint. Neither correction changed the business code or removed assertions. Before/after files and failed run logs remain retained. The full repository gate also found an English terminology conflict and an older venue detail fixture missing the new ownership menu label. The English recovery instruction now avoids the ambiguous term; the fixture adds only that label. Both failed full runs are retained: the first included both issues, and the second retained the missing fixture label. Separate independent amendments verify the copy change and unchanged fixture assertions. Evidence and transformation manifests live under app-owner-promotion/, app-owner-promotion-review/, app-private-tests-promotion/, app-certification-tests-promotion/, app-owner-navigation-tests-promotion/ and app-joined-tests-promotion/ within the ignored V4 audit directory. Canonical tests have no ignored runtime dependency.

Final local verification passes yarn check: production workspace types, 758 Node script tests with two existing skips, and all 393 Jest suites / 5,614 cases. The focused ownership cases also pass on Node 22 and Node 20. Full strict lint passed after the four UI repairs; the later English literal and one fixture field each passed targeted strict lint. The web production build passed after the UI repairs, before the English literal amendment. It used synthetic public connection settings; this is build evidence, not a hosted-service check. Existing Expo-location web-export and Next lint/bundle warnings remain recorded separately.

Remaining boundaries

The app workflow is integrated locally. Rendered host fixtures and synthetic geometry establish behavior under controlled input; they do not establish browser/device layout, Hermes execution, screen-reader usability or live push delivery. Full GoTrue, hosted ownership decisions and native transfer sharing remain outside this local evidence.

Mobile preflight reports fourteen dependency compatibility mismatches in the existing installation, including Expo/React Native patch levels, FlashList and keyboard controller. Mobile dependency manifests and the lockfile were unchanged by this app slice. This remains a mobile build-readiness boundary; the check is not reported as passing.

No hosted migration, push, Edge deployment, OTA or provider collection was performed. The fixed Naver evidence cohort remains 2,324/2,325, and the government response-envelope gate remains unverified. Neither gate is relaxed by ownership work. The wider backend audit follows venues, beginning with account-bound offline replay and then money/capacity, push delivery, membership/ratings, privacy/media and reference feeds.

Markdown remains the source of truth. Run yarn docs:check before handoff.