Repository navigation
Conversation
bokelley
force-pushed
the
fix/6827-identity-containment
branch
3 times, most recently
from
September 14, 2026 20:40
4120a39 to
6e35597
Compare
This was referenced Sep 14, 2026
bokelley
force-pushed
the
fix/6827-identity-containment
branch
2 times, most recently
from
September 17, 2026 12:47
c5873d6 to
9fa7707
Compare
This branch has not been deployed
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.
An automatic match against denormalized email can bind a Slack principal to an existing WorkOS credential, lending that credential's platform-admin or committee-leader authority to the Slack principal. This change refuses
mapping_source: 'email_auto'atSlackDatabase.mapUserbefore credential lifecycle entry, authorization epoch changes, mapping SQL, or name backfill, including when a caller supplies a transaction client.Containment only: #6827 remains open. Explicit token-correlated
user_claimedand global-adminmanual_adminlinking retain their existing behavior. Historical mappings and historical side effects remain effective; this is not complete Slack reversal or integrity remediation.Exact publication boundary
fix/6827-identity-containment/ #74599a7cd5362787a0badbfccd0f1cb1dd002654c22fee7076b5bb50e23a4553045a144d28b2f7925cde0ae2b26d8dbbd36e0b2021e575b70aa00cd6f723This is a sibling containment slice on exact #7459, not a stack on #7464 or #7460. Only the implementation head is published. The synthetic local #7450 composition commit and tree are excluded from this branch and PR.
No migration, historical cleanup, or protocol changeset. Draft review only; auto-merge must remain off. No ready-for-review transition, approval, merge, deployment, or settings change is authorized by this publication.
GitHub CI coverage and landing requirements
This PR is not landing-ready. GitHub currently has only stacked-PR metadata and auxiliary checks on exact head
ee7076b5bb50e23a4553045a144d28b2f7925cde; full implementation CI is not scheduled and cannot schedule through the currentpull_requestworkflow filters while the base isfix/6827-identity-containment/ #7459.Build Check and Dependency Review accept PR bases
main,develop,3.1.x, and3.0.x; CodeQL acceptsmain,3.1.x, and3.0.x; Semgrep, Check Migration Numbers, and Migration Smoke Test acceptmain. None accepts this stack base. Passing metadata checks therefore do not establish a full GitHub CI pass. The current checks are IPR Agreement, IPR Policy / Signature, and GitGuardian (passed), with AI PR Review and Mintlify (skipped).The coordinator reports that root independently reviewed exact #7498, found no blocker, and passed 26/26 focused tests. That read-only review and the local validation below do not replace the missing GitHub CI or constitute approval to land.
After #7459 lands, this slice must be restacked onto
main, receive full GitHub CI on the exact resulting candidate head, receive a fresh security review of that same head, and obtain human approval before landing. This requirement does not authorize restacking or changing this PR's head, base, Draft state, reviewers, or auto-merge now. Containment only; #6827 remains open.Caller coverage and stable outcomes
The seam throws
SlackEmailAutoLinkContainedErrorwith stable codeslack_email_auto_linking_disabled, distinct from infrastructure failure. All three production email-auto callers recognize it before link-derived preference transfer, chapter or organization writes, downstream WorkOS membership calls, success caches, or link counters.team_jointryAutoMapByEmailreturnscontained; a matched attempt stops before profile upsert, preference transfer, welcome/prospect work, chapter sync, or success invalidation, including when no Slack discovery row exists yet./auth/callbackemail fallbacktryAutoLinkWebsiteUserToSlackreturnslinked: falsewith the stable reason; existing link-success branches are not entered.user.createdorganization_membership.createdslack-auto-linkjobcontainedseparately from errors; zero linked/chapter/org/hint counters; no mapped-success set insertion.POST /api/admin/slack/auto-link-suggestedPOST /api/admin/slack/syncauto_mapped: 0and no identity mapping calls.user_change, Slack channel/message activity, and WorkOS update webhooks do not add another email-auto mapping implementation. Contacts' separateemail_autosource is unrelated to Slack identity linking. Generic explicit link/unlink behavior is not expanded.Validation on the exact implementation tree
Counts below overlap where focused files are included in broader suites; they are not additive totals.
The implementation commit passed the normal pre-commit hook without bypasses. At publication, the advisory pre-push storyboard matrix was selected by the hook's fallback comparison to
origin/main, although this PR changes no training-agent or compliance files. All seven tenant runs failed capability resolution before producing test totals: the local compliance cache is3.2.0-rc.2, while the test seller advertises through3.2-rc.1. Publication retried with the documentedADCP_SKIP_STORYBOARD_MATRIX=1override, which also skips the subsequent local 3.0 storyboard compatibility run. Full GitHub CI remains required for landing but cannot schedule against the current stack base, as explained above. Version synchronization, changeset scope, schema-link checks, and 55/55 documentation navigation tests passed on the retry. No implementation changes or hook edits were made.Focused commands:
npx vitest run --config server/vitest.config.ts tests/unit/slack-email-auto-containment.test.ts npx vitest run --config server/vitest.config.ts tests/unit/native-auth-http-wiring.test.ts # DATABASE_URL points only to the isolated Docker PostgreSQL fixture. npx vitest run --config server/vitest.config.ts \ tests/integration/slack-email-auto-containment.test.ts \ tests/integration/slack-db-name-backfill.test.ts \ tests/integration/workos-user-deletion-race.test.ts \ tests/integration/workos-user-deleted-primary.test.ts \ tests/integration/mcp-oauth-deletion-race.test.ts \ tests/integration/authorization-deletion-cross-replica.test.ts \ tests/integration/authorization-epoch.test.ts \ tests/integration/identity-layer.test.ts \ tests/integration/admin-link-unlink-credential.test.ts \ tests/integration/admin-promote-credential.test.ts \ tests/integration/workos-sync-email-domain.test.ts npm run typecheck npm run test:migrations git diff --check 9a7cd5362787a0badbfccd0f1cb1dd002654c22f ee7076b5bb50e23a4553045a144d28b2f7925cde git diff --exit-code 9a7cd5362787a0badbfccd0f1cb1dd002654c22f ee7076b5bb50e23a4553045a144d28b2f7925cde -- server/src/db/migrationsPostgreSQL tests compare complete rows serialized by PostgreSQL, including timestamps and metadata: Slack mappings, users, identity/credential edges, authorization epochs, organizations/memberships/domains, working groups/memberships/leaders/topics, administrator audit rows, preferences, aliases, relationships, and #7459's user CASCADE/SET NULL snapshot inventory. Repeated active-admin and ordinary committee-leader attempts remain inert and do not acquire Slack authority. Historical mappings of every source remain unchanged; explicit manual linking is a positive authority control.
Two #7459 deletion-race fixture writers now use explicit
user_claimed/manual_adminsources so they still reach and test the lifecycle fence. New email-auto tests separately prove rejection happens earlier. The deletion/race/recovery assertions remain in place.Deterministic composition plan
Exact #7450:
5595e6ce6eda4d8faf54b92c7b93c6b1c63b1d1eA separate local composition was tested; it is not included in this PR. It proved real
resolveSlackUserAAOAdminAccessreturnsforbidden/unmappedandcanScheduleMeetingsremains false after containment, with positive explicit-link controls for both an administrator and an ordinary committee leader. The independent reviewer checked the semantic reconciliation; #7450's administrator implementation remained byte-identical to its published version.To reproduce after separate composition authorization:
server/src/addie/admin-status-lookup.ts,server/src/addie/mcp/admin-tools.ts,server/tests/unit/aao-admin-status.test.ts, andserver/tests/unit/addie-admin-global-auth.test.ts. Retain fix(addie): authorize admin tools by authenticated credential #7450's uncached, typed credential-based authority lookups and its ID-only group lookup; retain fix(auth): contain destructive identity consolidation #7459's credential lifecycle fixture and repeated positive-lookup/freshness controls. Do not restore positive or negative administrator caching.Local composition evidence: 20 selected unit/integration files, 265 final tests passed, with changed files rechecked after adaptation. The initial run had 263/264 passed and one legacy deleted-primary test failed because #7450 removed the cache getter. After the test compatibility adjustment, its entire 23-test file passed. The enhanced composition containment file then passed 13 tests, including the added ordinary-leader positive control. Source typecheck and diff guards passed. These are composition results, not additional tests or commits in this PR, and do not claim a full audit of all #7450 surfaces.
Exact #7476:
71e684617cadd0d52683f11e55b51002fe2233a2Start from this slice's
server/src/slack/sync.tsand add exactly:import { withAuthorizationEpochBump } from '../db/authorization-epoch-db.js';organization_membershipsINSERT incheckAndAssignOrganizationByDomainwithwithAuthorizationEpochBump([workosUserId], client => client.query(...)).autoAddVerifiedDomainUsersAsMemberswithwithAuthorizationEpochBump([user.workos_user_id], client => client.query(...)).Preserve the email containment import/catches, mapping-result fences, and both #7459 early domain-assignment deferrals. Taking #7476's whole file would remove those deferrals and the website lifecycle-result fence. The import overlap was reconciled in a local copy; the resulting textual delta contains only the import and two epoch wrappers. This is a deterministic textual reconciliation, not a runtime #7476 composition claim.
Broader #7476 integration has baseline conflicts outside
sync.ts. Preserve #7459's credential deletion protections while adding #7476'swithAuthorizationEpochBump,getExactCredentialAuthorizationEpoch, and dispatch-time credential/epoch/administrator/organization checks. Reruncredential-grant-epoch-routes,authorization-epoch,addie/slack-mutation-authority,addie/slack-mutation-production-wiring,addie/mutation-authority, and the containment/deletion suites. An incorrectly established email binding would pass subsequent epoch checks, which is why refusal must remain before establishment.Limitations
Open workspace in Conductor
Draft disposition — 2026-10-09
This draft is retained for the stated workstream. Continue on this existing branch; no parallel PR is needed. This disposition does not waive CI, review, migration, or release gates.