Skip to content

Текущий код, миграция и самопроверка проекта ​

Исторический проект

Эта страница фиксирует прежний проект, а не текущий статус выпуска. Подготовка ресурсов, scoped authorization и trusted MCP уже реализованы в коммитах Agentfy; см. контракт серверного чата и границы доказательств. Браузерные/BONSITE протоколы и более широкие предложения по оплате/жизненному циклу сохраняют свои условия выпуска. Боевой запуск партнёра не подразумевается.

Факты текущего исходного кода ​

Сокращённые пути находятся под api/src/slices/, если полный префикс api/ не указан; исходники прочитаны в checkout AGNT2-424. Требуемые изменения не являются уже работающим поведением.

Текущее доказательствоСледствие и миграция
api/src/slices/user/user/user.prisma: обязательный unique email, optional password, platformRoleСубъект независимо от credentials, nullable/неприменимый email внешних акторов без фиктивных адресов; уникальность прямых credentials сохраняется
user/auth/domain/auth.types.ts: email обязателен в IAuthUser/JWT, union access/refresh/sessionЯвные scoped principal/source/audience, версионирование DTO/SDK; не расширять глобальный guard одной новой строкой
user/auth/domain/auth.service.ts: захват passwordless stub по email, новая команда, вызов foundingОтдельный credential-only/link/bootstrap; не захватывать заглушки, не создавать лишнюю команду, исключить внешних акторов из founding
user/auth/guards/jwtAuth.guard.ts: signature/type, sub/email в requestПроверка revocation state, явное разрешение endpoints для partner/linked; credentials/platform/financial-consent требуют прямого proof
user/auth/domain/auth.service.ts: refresh проверяет type и наличие user, выдаёт новые токеныPersisted rotating families, source/epoch/version/reuse detection; сегодня такого отзыва нет
user/team/domain/team.service.ts: раздельные team/key, seat и provisioningТранзакционный allocation gateway + durable outbox; текущий метод не атомарен
user/team/domain/teamProvision.port.ts: ошибки handlers логируются и подавляютсяХранить readiness/retry; успешный signup не гарантирует консьержа
user/userTeam/userTeam.prisma, domain/userTeam.service.ts: unique user/team, несколько owners, count перед записьюРоль остаётся источником владения; lock/transaction для последнего owner/transfer и состояния неактивных субъектов
agent/agent/agent.prisma: составной FK Agent(ownerId, teamId)→UserTeam(userId, teamId)ID субъектов сохраняются; передать агентов либо сохранить неактивное членство и остановить jobs
billing/{subscription,invoice,payment,paymentMethod}/*.prisma: team scope, invoice unique subscription/period, cascade командыTimeline плательщика и retained invoice lines; не переносить старые подписки/историю, убрать риск удаления финансов перед новым биллингом
billing/invoice/domain/invoice.service.ts, billing/payment/domain/payment.service.ts: invoice после completed paymentТекущий PayPal subscription flow не usage-invoicing; проверить мандаты, отмену и callbacks обоих режимов
system/usage/meter/meter.prisma: frozen costUsdPico, ID без resource FK, rollupsСохранить ledger/точность, добавить историческую коммерческую атрибуцию events/aggregates до смен плательщика

Размещение по CleanSlice ​

Прочитаны MCP get-started, list-categories, выполнены запросы о cross-slice authentication/organization и transactions/idempotency/billing, прочитан docs/architecture/dependency-flow.md. Второй запрос не нашёл transaction guide: предложенная транзакция — наше решение, не выдуманное правило MCP. Дополнительно действуют слои проекта и constitution.

Контракты organization/identity/membership — singular slices user-группы; user auth владеет browser/link contexts. Billing L6 координирует provisioning, которому нужны user allocation L2 и payer state, через domain gateway с единой локальной транзакцией в data implementation. План обязан определить общий transaction boundary, не назвать набор независимых service calls атомарным. Agent L5 получает durable operation через зависимости вниз; внешние эффекты вне транзакции.

System usage L1 не импортирует user/billing. Верхние потребители передают неизменяемую атрибуцию через нижние domain ports/snapshots; устаревший snapshot проверяется до платного dispatch. Domain не зависит от Prisma, DTO/validation — presentation, persistence/mapping — data, cross-slice — aliases/barrels. Prisma sources и SDK меняются только при реализации, не в этой задаче.

Expand, backfill, gate, contract ​

ФазаКритерий перехода
1. Расширение под выключенными flagsТаблицы org/external/link/session/operation/outbox/payer; совместимый direct auth; partner routes default deny
2. BackfillUser/Team/Agent ID, владельцы, планы, платежи/подписки не меняются; текущие команды → Agentfy; только доказуемая атрибуция истории, неоднозначности в карантин
3. Auth/allocationNo-email end-to-end, два proof, endpoint opt-in, версионированная lifecycle sync, atomic bootstrap/owner guards; все A-сценарии исполнимы
4. BillingОба режима v1, реальный provider consent/cutover/reconciliation, retention, hard budget, спонсирование; платного пилота до этого нет
5. ПилотTest namespace, затем ограниченная production org; измеренные cancellation/lease, безопасная сериализация, EN/RU/UK UX и recovery
6. ContractУдаление legacy email assumptions только после старых клиентов/токенов и совместимости rollback readers

Отдельные flags: provisioning, browser/link, paid billing. Rollback запрещает выдачу/платный dispatch, сохраняет субъектов, связи, tombstones, ledger и назначения; outbox/provider эффекты дренируются и сверяются идемпотентно. Возврат к бинарникам, не понимающим no-email actor, после их появления небезопасен: оставить совместимые readers либо roll forward. Нельзя откатывать объединением пользователей, удалением истории или повторной выдачей внешнего ID.

Нумерованный разбор атак и гонок ​

Это ожидаемые результаты проекта и будущие тесты, не отчёт о пройденных runtime-тестах.

IDУсловия и действиеОжидаемый результатТочка обеспечения / будущий тест
A01Два bootstrap с одним ключомОдин actor/team/owner/assignment/operationUnique receipt + transaction; concurrent HTTP test
A02Разные ключи/истёкшая receipt, тот же external teamSame fingerprint продолжает, изменение конфликтует; удалённый creator не возвращаетсяPermanent mapping; rotation/expiry/retry test
A03Сбой после commit до response/outboxТа же операция, нет бесхозной платной команды/дубликата агентаDurable outbox/step idempotency; crash injection
A04Ключ BONSITE передаёт чужие org/team/agentНераскрывающий отказ без чтения/записиNamespace по всей цепочке; routes/jobs/search/export suite
A05Злой issuer входит linked subjectТолько его партнёрские права, нет direct/private/other-org и link metadataSource-bound principal; все routes/serializers
A06Provision key вызывает browser issuance/payer acceptОтказ даже при известных IDScope + independent financial proof; negative API
A07Два direct аккаунта связывают один subjectОдна связь; без раскрытия второго аккаунтаSubject lock/unique; race test
A08Совпадает email invite/direct/partnerНет auto-link, claim credentials, смены целиНезависимый proof/fixed target; forwarded invite
A09Чужой callback/code, неверный browser/PKCEНет сессии или подмены аккаунтаState/nonce/binding; login-CSRF/leak
A10Две вкладки redeem code, replay/expiry/cancelОдин победитель, без посторонней смены контекстаAtomic consume/tab context; browser race
A11Unlink, затем старый JWT/refresh/socket/downloadПроизводный доступ закрыт; независимые сессии сохраненыLink epoch/family/proxy; stream/refresh
A12D→P→иная связь, refresh partner→directНет объединения/повышенияOne-hop/immutable source; graph/token tests
A13Два владельца одновременно снимают себяОстаётся активный ownerTeam lock/version; transaction race
A14Отзыв последнего external owner с живыми агентамиОтзыв успешен, команда/jobs остановлены, без auto-promoteLifecycle/owner checks; live cancellation
A15Удаление владельца агентов или transfer без payer consentЯвная передача/остановка, payer прежнийFK/workflow; jobs/ownership
A16Cutoff, поздний usage и duplicate callbackОдна историческая атрибуция, без дубля денег/счётаTimeline lock/occurredAt/dedup; boundary reorder
A17Два резерва последнего бюджета, provider timeoutНет перерасхода/раннего releaseAtomic reservation/reconciliation; fault test
A18Sponsor отозван при pending payerПлатная работа только при валидном покрытии; owner не платит самRevalidate activation; sponsor-removal
A19Subject удалён, приходит старое active событиеНет активации или продления lease старой/повторной ревизиейMonotonic revision/tombstone; replay/reorder
A20Удалённая команда повторяет bootstrapTombstone/unavailable, не новая команда/сессияPermanent ID/current state; delete/retry
A21BONSITE исчез/закрылся при team-paidРабота org запрещена, direct/private доступны, нет auto-moveStatus/subject lease; outage/closure
A22Скомпрометирован issuer, готовы коды/связиProof/code отозваны, links в карантине; direct credentials целыCredential/epoch/provenance; incident interval
A23Прежний payer исключён, читает свой счётInvoice-only, без контента командыPayer ACL отдельно; invoice auth
A24Credentials из partner flow на пустой установкеНет лишней команды/агента/founderDedicated flow/founding exclusion; empty install
A25Delete direct vs unlink vs deprovisionРазные эффекты, другой actor/team/debt сохранён, grants не оживаютLifecycle/relink integration
A26Test key/worker/guest token в production user APIОтказ даже при валидной подписи/известном IDEnvironment/audience/type; token matrix
A27Owner transfer после изменения membership/policyОтказ без частичного пониженияProof/version; accept/revoke race
A28Нет state store или subject lease истёкFail closed, старое событие/heartbeat lease не продлеваетAction gate + fresh subject proof; outage/replay
A29Внешний owner приглашает свой direct accountОтказ; только внешние customer actors своего namespaceTarget policy; deprovision bypass test
A30Org-paid A30+B70, team-paid C20, внутреннее спонсированиеСчёт org100, C20 отдельно, sponsorship не выручка; один direct payer не объединяет счета командMode/team grouping key; mixed-payer invoice test

Найденные и исправленные проблемы ​

Ранее режим оплаты был открытым вопросом: теперь оба обязательны в v1. Глобальный merge заменён стабильными субъектами. Provisioning отделён от browser issuance; явно признана способность issuer действовать как свои пользователи. Прямые приглашения в клиентские команды партнёра запрещены, иначе обходился deprovision. Последний owner не мешает отзыву по безопасности. Idempotency переживает ротацию/expiry без воскрешения ресурсов. Контакт, владение и финансовое согласие разделены; local allocation атомарен, внешняя готовность асинхронна. Дополнительно уточнены service initiator против owner, фиксация subject/code, quarantine после компрометации, lease отдельного subject и продажная стоимость бюджета.

Сроки, cutoff и lease — рекомендации, не новые подтверждённые требования пользователя. До выпуска обязательны: provider обоих режимов, измеренная отмена/lease, процедура проверки личности при recovery, retention/legal policy, проверенная совместимость протокола. Непройденный gate блокирует соответствующую возможность; нельзя спрятать безопасность за «потом». Перенос между организациями, защита от самого identity issuer и вложенные реселлеры вне v1; закрытие означает разрешённый экспорт/support, не автоматический перенос.

Walkthrough не обнаруживает противоречий инвариантов после исправлений. Проект готов к обсуждению дизайна с указанными release gates, не является доказательством безопасности или разрешением выпустить runtime.

Проверка документации ​

Проверить VitePress, локальные ссылки/якоря, navigation и паритет EN/RU/UK разделов/сценариев. Фактические результаты make check, app/admin builds и текущих HTTP startup checks записываются в PR. API/app не меняются; результатов новых runtime-тестов нет. Проследить три пути — прямой signup, external-only BONSITE, связь существующего direct — и A01–A30 по контрактам.