fix(dashboard): complete multi-tenant migration and repair broken main - #273
Merged
Lakes41 merged 1 commit intoJul 24, 2026
Merged
Conversation
This was referenced Jul 24, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Finishes the multi-tenant migration described in
docs/multi-tenancy.mdand repairs main, which currently does not build: merge7ba7304committed conflict markers in 7 files, and PRs #267/#268/#269 left literal`nsequences, a splicedSessioninterface, a dead duplicate POST block inapi/guilds, and an emptiedadapters/mock.ts.Linked Issue
Closes #263
Type of Change
Changes Made
lib/repositories/types.ts+adapters/mock.ts: every member/pass repository method takesguildIdas first parameter. Mock implementations rewritten (the file was empty on main): per-guild scoping via agetScopedhelper, wallet uniqueness keyedguildId::wallet, optimistic concurrency viaversion(ConflictErroron stale expectedVersion),streamAllfor members. Defaults match the spec: passes startdraft/currentSupply: 0, members startpending.adapters/durable.ts: same tenanted signatures;DurablePassRepository/DurableMemberRepositorystubs added (throw until the SQL backend lands), guild update no longer allows overwriting derivedmemberCount/passCount.lib/validation/mutations.ts:guildIdadded toSERVER_OWNED_FIELDS(clients sending it get 400, per spec),.passthrough()removed from the four mutation schemas,invalid_type_error/errorMapconverted to the zod v4errorparam (the repo pins zod ^4.4.3; the v3 params are gone from the types),flattenZodIssuesreads v4invalid_union.errors.guildId:api/passes,api/members(PATCH now readsexpectedVersion),api/admin/reconcile,scripts/reconcile.ts,api/verifyimport path fixed.lib/auth/session.ts: rebuilt the splicedSessioninterface (guild-scopedroles/activeGuildId, optionalcsrfTokenfor bearer sessions); mock sessions deduplicated.api/guilds/route.ts: removed the dead old POST block left after the merge.packages/env: splitdashboardEnvBaseSchema(field-level, used by plain runtime reads) fromdashboardEnvSchema(strict, used at startup/live-mode construction). ReadinggetApiMode()no longer requires live-mode secrets, and validation results are no longer cached.packages/integration-client: restoredActivityChange,SENSITIVE_AUDIT_FIELDS, and thechangesfield on activity events (dropped by the bad merge; audit-diff tests depend on them).`ndamage inapp/activity,app/members,lib/hooks/useActivityFeed,lib/activity/query,test/activity-query.test.ts, andpackages/webhook-utils/test/verify.test.js(the file also had a truncated test and mismatched braces; rebuilt against the pre-Expand webhook-utils signature edge case tests #268 version, keeping the new tests).test/repositories/contracts.tsincludingpassRepositoryIsolationContractandmemberRepositoryIsolationContract(cross-guild access behaves as missing, wallets unique per guild, updates/deletes can't cross tenants). Updated stale fixtures to the tenanted shapes (guildId,version) and checksummed wallets; live tests now set the env vars they need.Test Evidence
npx tsx --testper file, full dashboard suite (test/*.test.ts+test/repositories/*.test.ts):Package suites:
tsc --noEmit(TypeScript 5.6.3, per repo pins) onapps/dashboard: no errors (in my sandbox the only diagnostic istailwindcsstypes missing because I could not run a full pnpm install; the dep is declared).eslinton the touched trees: 28 errors / 41 warnings, every one pre-existing in code this PR does not touch (session-store.test.ts,reconciliation,DashboardLayout,webhook-utils/src/verify.ts, etc.). For comparison, main currently fails to even parse 7 files, so a like-for-like lint of main is not possible. This branch introduces zero new lint findings.Accessor audit (requested in #263)
Every read/write of the member and pass repositories now flows through guild-scoped methods:
app/api/passes/route.ts— GET/POST/PATCH/DELETE passgetActiveGuildId(request); DELETE usesdelete(guildId, id).app/api/members/route.ts— GET/POST/PATCH scoped; PATCH destructuresexpectedVersionand returns 409 onConflictError; client-suppliedguildIdrejected with 400 by the schema.app/api/admin/reconcile/route.tsandscripts/reconcile.ts— iterate guilds, count per guild.lib/repositories/adapters/mock.ts—getScopedmap per guild; cross-guild id access returns not-found.app/api/guilds/route.ts— counts derived from the scoped repos.Isolation regressions live in
test/repositories/contracts.tsand run against any adapter viamock-contract.test.ts(63 tests).Checklist
pnpm typecheckpasses with no errors (rantsc --noEmitdirectly with the pinned TS 5.6.3; see note above)pnpm lintpasses (or issues are pre-existing and documented) — all 28 remaining errors pre-date this PR; none are in new/modified logicpnpm testpasses (all existing tests still pass)next devin this sandbox (no full pnpm install); routes are exercised by the route-level test suite instead.env.example(no new variables)docs/multi-tenancy.mdspec)Additional Notes
apps/access-apiandapps/discord-bottests were not run here; they need@prisma/client/discord.jswhich I could not install, and this PR does not touch either app.