Skip to content

Current-code mapping, migration and design self-audit ​

Historical design snapshot

This page records the earlier design scope, not current release status. Agentfy now has committed provisioning, scoped authorization and trusted MCP foundations; see the implemented server-chat contract and evidence boundary. Browser/BONSITE protocols and broader billing/lifecycle proposals below retain their own release gates. No live partner deployment is implied.

Current source evidence ​

Source paths below are under api/src/slices/ unless the full api/ prefix is shown. These facts were read in the AGNT2-424 checkout; proposed changes must not be mistaken for current behavior.

Current evidenceConsequence and required migration
api/src/slices/user/user/user.prisma: mandatory unique email, optional password, platformRoleExpand to a credential-independent actor and nullable/non-applicable email for partner actors; no dummy addresses. Direct credential uniqueness remains enforced.
user/auth/domain/auth.types.ts: IAuthUser and user JWT require email; token union is access/refresh/sessionIntroduce explicit scoped principal/source/audience contracts; version DTOs and regenerate SDK, do not casually rename fields or broaden the global guard.
user/auth/domain/auth.service.ts: registration claims passwordless email stubs; new users get a team; registration invokes foundingDedicated credential-only/link and partner bootstrap flows; no email-stub takeover, extra team or partner founder promotion. Audit founding selection to exclude external actors.
user/auth/guards/jwtAuth.guard.ts: access signature/type checked, request receives sub/emailState-backed revocation and explicit endpoint opt-in for partner/linked principals; account, platform and financial-consent routes demand direct proof.
user/auth/domain/auth.service.ts: refresh verifies token type and user existence, then issues tokensAdd rotating persisted session families, source/epoch/version checks and reuse detection before claiming unlink/revoke works. Current code does not implement this.
user/team/domain/team.service.ts: team/key, owner seat and provisioning are separate awaited writesReplace provisioning entry with an explicit transactional allocation gateway plus durable outbox; do not describe the current method as atomic.
user/team/domain/teamProvision.port.ts: handler exceptions logged/swallowedPersist readiness/retries; a successful current signup is not proof concierge setup succeeded.
user/userTeam/userTeam.prisma: unique actor/team; role string permits multiple owners; domain/userTeam.service.ts counts owners before mutationRetain role as ownership source; serialize last-owner/transfer operations, handle inactive owners and security suspension.
agent/agent/agent.prisma: composite Agent(ownerId, teamId) references UserTeam(userId, teamId)Keep actor IDs stable; reassign agents or preserve inactive memberships and suspend jobs before removal.
billing/{subscription,invoice,payment,paymentMethod}/*.prisma: team-scoped commercial records; invoice unique subscription/period, team cascadeAdd payer timelines and retained invoice lines without deleting history or moving old provider subscriptions; remove financial cascade risk before enabling new billing.
billing/invoice/domain/invoice.service.ts, billing/payment/domain/payment.service.ts: invoices written on completed-payment intakeCurrent PayPal subscription flow is not a usage-invoicing engine; certify mandate/cancellation/callback behavior for both payer modes.
system/usage/meter/meter.prisma: frozen costUsdPico, IDs without resource FKs; raw-event rollupsPreserve ledger and precision, add durable historical commercial attribution to events/aggregates before live payer changes.

CleanSlice mapping ​

Consulted CleanSlice MCP get-started, list-categories, searches for cross-slice authentication/organization dependencies and transactions/idempotency/billing, and full docs/architecture/dependency-flow.md. The second search returned no matching transaction guide; the transaction proposal here is an explicit design choice, not an invented MCP rule. The project layers and constitution further constrain dependencies.

Organization/identity/membership contracts belong in singular user-group slices; user auth owns browser/link contexts. Billing (L6) coordinates provisioning that requires both user allocation (L2) and payer state, using a domain gateway contract whose data implementation owns the local transaction. The implementation plan must specify a shared transaction boundary for those writes, not call independent service methods and label that atomic. Agent setup (L5) consumes the durable operation through downward contracts; no remote effect is inside the local transaction.

Lower system usage (L1) must not import user or billing. It accepts immutable attribution through lower-layer domain ports/snapshots supplied by upper consumers; preserve the existing inversion pattern and validate stale snapshots before paid dispatch. Domain has no Prisma dependency; DTO validation is presentation, persistence/mapping is data, and cross-slice imports use aliases/barrels. Per-slice Prisma sources and generated SDK contracts change only during implementation, never in this documentation task.

Expand, backfill, gate, contract ​

PhaseAcceptance gate before proceeding
1. Expand behind disabled flagsNew org, external mapping, link, session, operation/outbox and payer-history tables; direct auth remains compatible; partner routes default deny
2. BackfillExisting User/Team/Agent IDs, owners, plan IDs, payments and subscriptions unchanged; assign existing teams to Agentfy; reconstruct payer attribution only from evidence, quarantine ambiguous history for review
3. Auth and allocationNo-email actor end to end, two-proof links, endpoint opt-in, versioned lifecycle sync, transactional bootstrap and owner guards; all A scenarios below executable
4. BillingBoth organization-paid and team-paid v1 paths, real provider consent/cutover/reconciliation, invoice retention, hard budgets and sponsorship accounting; no paid pilot before passing
5. PilotTest namespace first, then limited production organization; cancellation/lease targets measured, sanitized serialization checked, EN/RU/UK UX and recovery exercised
6. ContractOnly after old clients/tokens and rollback readers are retired; remove legacy mandatory-email assumptions and obsolete paths after compatibility evidence

Separate flags govern partner provisioning, browser authorization/linking and paid billing. Disable issuance/paid dispatch on rollback; preserve actors, links, tombstones, ledger and assignments. Drain/reconcile committed outbox/provider effects idempotently. A rollback to binaries that cannot represent no-email actors is unsafe once such actors exist: retain compatible readers or roll forward. Never “roll back” by merging users, deleting history or restoring a reused external ID.

Numbered adversarial walkthrough ​

Each row is a design expectation and a future executable test, not a passing runtime test report.

IDSetup and actionExpected resultEnforcement point / future executable test
A01Two requests bootstrap same namespace/team with same keyOne actor/team/owner/assignment/operationUnique receipt + local transaction; concurrent HTTP integration test
A02Different keys or expired receipt target same external teamSame fingerprint resumes; changed payload conflicts, removed creator stays removedPermanent mapping/fingerprint; rotate key, expire receipt and retry test
A03Crash after local commit before response/outbox completionRecover same operation; no orphan charged team or duplicate agentDurable outbox + step idempotency; crash-injection test
A04BONSITE key supplies another org/team/agent IDNondisclosing denial, no read/writeWhole-chain namespace authorization; routes/jobs/search/export isolation suite
A05Malicious identity issuer logs in as linked partner subjectOwn-subject rights only; no direct/private/other-partner access or link metadataSource-bound scoped principal; enumerate all protected routes and serializers
A06Provision key calls browser issuance or direct payment acceptanceDenied regardless of known subject/account IDSeparate credential scopes + independent financial proof; negative API tests
A07Two direct accounts confirm link to same external subjectExactly one active link; loser learns no other account detailsSubject lock + unique active link; simultaneous confirmation test
A08Same email in invite, direct account and partner profileNo automatic link, credential claim or invite retargetIndependent proof + fixed target; collision/forwarded-invite tests
A09Attacker sends unsolicited login callback/code; wrong browser or PKCENo session and no account replacementAgentfy transaction binding/state/nonce; login-CSRF and code-leak tests
A10Two tabs redeem same code; replay, expiry or cancellationOne winner; other flows fail without context mutationAtomic consume + tab context; parallel redemption/browser tests
A11Unlink followed by stale JWT/refresh/socket/download useDerived context refused; unrelated direct and valid partner-origin sessions unaffectedLink epoch + session-family revocation/proxy; refresh and streaming tests
A12Traverse D→P→another link or refresh partner into directNo privilege union or source changeOne-hop context resolver and immutable source; graph/token-confusion tests
A13Two owners concurrently demote/remove themselvesAt least one active owner remainsTeam lock/version; concurrent membership transaction test
A14Last external owner security-revoked while agents runRevoke succeeds, team/jobs suspend, evidence retained; no arbitrary promotionSubject lifecycle + owner/agent checks; live-job cancellation test
A15Remove actor owning agents, or transfer owner without payer consentExplicit reassignment/suspension; payer unchangedMembership FK plus transaction workflow; background-job/ownership test
A16Payer cutoff races with usage, late event and duplicate callbackExactly one historical assignment per charge, no duplicate money/invoiceTimeline lock, occurrence attribution, dedup; boundary/reordered-event tests
A17Two jobs reserve remaining budget; one times out at providerNo overspend or premature reservation releaseAtomic budget reservation + reconciliation; concurrent fault test
A18Sponsor revoked while payer proposal awaits acceptancePaid work stops unless valid coverage remains; no automatic owner chargeActivation revalidation; pending-sponsor-removal test
A19Subject removed then stale activation arrivesOld/duplicate revision cannot reactivate or extend subject lease; restoration requires new grantsMonotonic lifecycle revision/tombstone; reordered webhook test
A20Team deleted then original bootstrap retriedTombstone/unavailable result, never new team or live accessPermanent external claim + current-state check; deletion/retry test
A21BONSITE disappears or org closes while team is team-paidOrg work denied too; direct/private teams remain usable, no silent migrationOrg status + lifecycle freshness; outage/closure test
A22Issuer key compromised; attacker prepared codes or linksRevoke pending proofs, quarantine affected links and sessions; direct credentials untouchedCredential/auth epoch + provenance; incident-time-range test
A23Old payer removed from team seeks historical billInvoice-only access remains, team data stays deniedPayer ACL separate from membership; invoice authorization test
A24Add direct credentials from partner context; first-user founder eligibleNo extra team/agent, no founder promotion; failed link leaves no duplicate resourcesDedicated credential flow + founding exclusion; empty-install test
A25Delete direct account versus unlink versus deprovision partnerDistinct effects; preserve other actor/team/debt and no renewed revoked grantsSeparate lifecycle commands; full lifecycle/relink test
A26Test key/worker token/guest token sent to production user routesDenied; known IDs or valid signature do not widen authorityEnvironment + audience/type policy; token matrix test
A27Owner transfer accepted after membership or org policy changedStale proposal rejected without partial demotionFresh proof/version + active membership; accept/revoke race test
A28Current-state store unavailable or partner freshness lease expiredFail closed; org heartbeat/stale event cannot renew subject leaseAuthorization gate; outage/lease-expiry test
A29Partner owner invites their own direct account into a partner teamRefused; only same-namespace external customer actors, so deprovision cannot be bypassedMembership target policy; direct-invite bypass test
A30Org-paid A30+B70, team-paid C20, internal sponsorshipOrg invoice100, C20 separately, sponsorship not revenue; same direct payer does not merge team billsMode/team grouping key; mixed-payer invoice test

Issues found and corrected during design ​

The earlier proposal left payer choice open and postponed team-paid behavior; both are now required in v1. Global-user linking would expose unrelated memberships; stable actors replace merges. A provisioning key is no longer also a browser-login credential. Claims that all organization operators are unable to read content were narrowed to reflect identity-issuer impersonation power. Direct invitations into partner customer teams are disallowed in v1 to prevent deprovision bypass. Last-owner protection now permits security suspension without orphan automation. Idempotency persists through rotation/receipt expiry without restoring deleted resources. Billing contact, ownership and accepted financial responsibility are separate transitions. Local allocation is atomic, but external provisioning readiness is asynchronous and honestly reported.

Additional corrections distinguish service initiator from owner, freeze the browser subject/code result, quarantine compromised-issuer links, renew leases per subject only from fresh reconciliation, and reserve billable sell-price rather than vendor cost.

The design uses explicit technical defaults for expiries, cutoffs and lifecycle leases. These are reviewable recommendations, not additional confirmed user decisions. Remaining implementation release gates are provider support for both payer modes, proven cancellation/lease timing, recovery verification procedure, retention/legal policy, and reviewed partner protocol interoperability. Failure of a gate blocks that capability; “later” must not enable an unsafe paid or login path. Cross-organization migration, privacy from the partner identity issuer and nested resellers remain outside v1; closure uses authorized export/support, not automatic transfer.

The walkthrough finds the documented invariants mutually consistent, subject to the release gates above. It is ready for design review, not a proof of security or permission to release runtime code.

Documentation validation ​

Validate VitePress build, local page/anchor links, navigation and EN/RU/UK section/scenario parity. Required project make check, app/admin builds and current HTTP startup checks are recorded in the PR report with actual outcomes. No API/app source is changed; there is no new runtime test result to claim. Reviewers should follow the three journeys—direct signup, external-only BONSITE user, existing direct account linking—and then trace A01–A30 against the contracts.