You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Epic β Decouple invitations from organizations (referral-ready)
Two invitation systems were colliding: the platform signup-gate (#3715, beta invite-only) and org membership email-invite. We fully decouple them.
Model: "invite a contact to the platform" (token + invitedBy + beta-gate eligibility) becomes a standalone optional invitations module depending only on auth. org becomes roster-of-existing-accounts only (add/roles/remove + join-requests). invitations β₯ org β they communicate via userId. Referral (#5) is schema-ready (invitedBy + invitation.accepted event), credit-grant logic deferred.
Spec:infra/docs/superpowers/specs/2026-06-09-invitations-org-decouple-design.md Plan:infra/docs/superpowers/plans/2026-06-09-invitations-org-decouple.md (audited on 4 axes + a Codex second-opinion pass folded in)
β οΈ Ordering constraint: Phase 1 (land #3715 byte-identical to Trawl's deployed state) MUST merge before Phase 2 (module extraction), otherwise the next Trawl /update-stack produces a 3-way conflict on auth.controller.js.
Locked decisions: no auto-verify of invite-created accounts Β· lowercase + case-insensitive unique index on users.email Β· cap TOCTOU overshoot accepted + documented Β· add-to-org β PENDING with source:'owner_add' (E15 β never confused with a join-request) + persistent pending-list in Account + transient snackbar.
Phases (each = its own PR via /feature β /verify β /dev:verify-qa β /dev:pull-request-finalize):
Sub-issues are linked below and tracked by the Sub-issues progress bar.
π Fable review corrections (2026-06-10, code-verified vs origin/master)
π feat(auth): invite-only / capped signup gateΒ #3715 is ALREADY MERGED on origin/master (the spec/plan were authored from a local checkout 115 commits behind). f0e7a83c is an ancestor; all modules/auth/**/*invitation* + auth.signupCapacity.js + gate hunks are present; trawl_node master auth.controller.js is hash-identical. β P1 (π§ Land #3715 signup-gate on master (byte-identical)Β #3809) collapses to a verify-no-op. The "Node backend not on master / front-ahead-of-back" premise is FALSE.
π΄ Casing bug across P5a: membership status is stored lowercase (PENDING:'pending'); any === 'PENDING' check (incl. the prescribed pre('validate') consent guard) is INERT β use the MEMBERSHIP_STATUSES.PENDING constant everywhere.
π΄ P2 must ship a /api/auth/invitations deprecation alias kept until P6 repoints the Vue store (else the live admin tab breaks for ~4 PRs).
Before executing ANY phase: git fetch && git checkout origin/master and re-derive file/line refs (local tree is stale; org signup-join flow was reworked β domain-match auto-join removed β suggestedJoin).
Epic β Decouple invitations from organizations (referral-ready)
Two invitation systems were colliding: the platform signup-gate (
#3715, beta invite-only) and org membership email-invite. We fully decouple them.Model: "invite a contact to the platform" (token +
invitedBy+ beta-gate eligibility) becomes a standalone optionalinvitationsmodule depending only onauth.orgbecomes roster-of-existing-accounts only (add/roles/remove + join-requests).invitations β₯ orgβ they communicate viauserId. Referral (#5) is schema-ready (invitedBy+invitation.acceptedevent), credit-grant logic deferred.Spec:
infra/docs/superpowers/specs/2026-06-09-invitations-org-decouple-design.mdPlan:
infra/docs/superpowers/plans/2026-06-09-invitations-org-decouple.md(audited on 4 axes + a Codex second-opinion pass folded in)#3715byte-identical to Trawl's deployed state) MUST merge before Phase 2 (module extraction), otherwise the next Trawl/update-stackproduces a 3-way conflict onauth.controller.js.Locked decisions: no auto-verify of invite-created accounts Β· lowercase + case-insensitive unique index on
users.emailΒ· cap TOCTOU overshoot accepted + documented Β· add-to-org βPENDINGwithsource:'owner_add'(E15 β never confused with a join-request) + persistent pending-list in Account + transient snackbar.Phases (each = its own PR via
/featureβ/verifyβ/dev:verify-qaβ/dev:pull-request-finalize):invitationsmodule + eligibility-hook inversion (E13 query token) Β· Nodeorg.addMember(userId)+sourcediscriminator + consent Β· NodeinvitationsVue module + account/admin tabs + gap-fixes Β· VuereferredByschema +invitation.accepted) Β· NodeSub-issues are linked below and tracked by the Sub-issues progress bar.
π Fable review corrections (2026-06-10, code-verified vs origin/master)
origin/master(the spec/plan were authored from a local checkout 115 commits behind).f0e7a83cis an ancestor; allmodules/auth/**/*invitation*+auth.signupCapacity.js+ gate hunks are present; trawl_node masterauth.controller.jsis hash-identical. β P1 (π§ Land #3715 signup-gate on master (byte-identical)Β #3809) collapses to a verify-no-op. The "Node backend not on master / front-ahead-of-back" premise is FALSE.PENDING:'pending'); any=== 'PENDING'check (incl. the prescribedpre('validate')consent guard) is INERT β use theMEMBERSHIP_STATUSES.PENDINGconstant everywhere./api/auth/invitationsdeprecation alias kept until P6 repoints the Vue store (else the live admin tab breaks for ~4 PRs).git fetch && git checkout origin/masterand re-derive file/line refs (local tree is stale; org signup-join flow was reworked β domain-match auto-join removed βsuggestedJoin).