Some checks failed
Architecture Governance / architecture (push) Has been cancelled
- Track A: analytics event pipeline (traffic/catalog/commerce/operational/ quality events), synthetic-traffic separation enforced server-side by environment/token, never a client-settable flag. - Track S: 17-role/3-scope RBAC enforcement, audit log, secrets, rate limiting, step-up auth - closes this session's most serious finding (admin role model is decorative today, any authenticated admin has full access regardless of assigned role). - docs/backend/README.md: index of all 12 contract docs (Phases 1-10 + 2 tracks) in build order, plus what's deliberately excluded (namespace migration, per-connector adapters, extra payment providers) and the one thing still genuinely open across all of them - backend ownership. - Cross-linked from BACKEND-API-REFERENCE.md and the delivery plan so the index is discoverable from either entry point. This closes out documentation for every phase/track in PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md that doesn't require a further business decision. Nothing left undocumented on our side pending only implementation and backend-ownership assignment. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
84 lines
4.1 KiB
Markdown
84 lines
4.1 KiB
Markdown
# Track S Backend Contract — RBAC, Audit, Secrets, Rate Limiting
|
|
|
|
Companion to [PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md](../PRODUCT-PLAN-v3.1-DELIVERY-PLAN.md) Track S. Covers plan §4.4, §10.
|
|
|
|
**Status: ready to build. Gates the launch — this is the single most serious security gap identified in this session's audit.** Today the admin role model is decorative: `AdminRole` and permissions exist as types, but nothing gates any button, page, or action anywhere in the app. Any authenticated admin has full access.
|
|
|
|
---
|
|
|
|
## 1. Roles (17 total, 3 scopes, per plan §4.4)
|
|
|
|
```ts
|
|
type PlatformRole = 'PLATFORM_OWNER' | 'TECH_ADMIN' | 'SECURITY_ADMIN' | 'DOMAIN_MANAGER' | 'VIEWER';
|
|
|
|
type MarketplaceRole =
|
|
| 'MARKETPLACE_ADMIN' | 'CONTENT_MANAGER' | 'CATALOG_MANAGER' | 'ORDER_MANAGER'
|
|
| 'FINANCE_MANAGER' | 'SUPPORT_MANAGER' | 'VIEWER';
|
|
|
|
type SellerRole =
|
|
| 'SELLER_OWNER' | 'SELLER_CATALOG_MANAGER' | 'SELLER_ORDER_MANAGER'
|
|
| 'SELLER_FINANCE_VIEWER' | 'SELLER_VIEWER';
|
|
```
|
|
|
|
`SellerRole` is already specified in [Phase 5's contract](PHASE-5-SELLER-PORTAL-CONTRACT.md) §4 — this doc adds the platform and marketplace scopes around it.
|
|
|
|
## 2. Enforcement (backend-side, non-negotiable)
|
|
|
|
Every `/api/admin/v2/*` and `/api/platform/v1/*` endpoint must check `(role, tenantScope)` against the acting user's session — **before** touching data, not as a post-hoc filter. `tenant scope` here means: a `MARKETPLACE_ADMIN` for marketplace A must get a `403` (not an empty result) querying marketplace B's data, never a silently-scoped response that looks like "there's just nothing here."
|
|
|
|
```
|
|
GET /api/identity/v1/session/permissions -> { role, scopes: string[], marketplaceIds: string[] }
|
|
```
|
|
|
|
Frontend route/action guards derive from this endpoint's response — never hardcode role logic client-side beyond hiding UI affordances (which is convenience, not security).
|
|
|
|
## 3. Audit log
|
|
|
|
```ts
|
|
interface AuditEvent {
|
|
id: string;
|
|
actor: string;
|
|
action: string; // e.g. 'role.changed', 'offer.price_updated', 'refund.approved'
|
|
entityType: string;
|
|
entityId: string;
|
|
before?: unknown;
|
|
after?: unknown;
|
|
reason?: string;
|
|
occurredAt: string;
|
|
ip?: string;
|
|
}
|
|
```
|
|
|
|
Mandatory coverage (plan §10.1): permission changes, seller status changes, catalog moderation actions, price changes, payment/refund actions, manual order overrides, integration credential changes, production launch actions.
|
|
|
|
```
|
|
GET /api/admin/v2/audit?marketplaceId=&entityType=&actor=&from=&to=
|
|
```
|
|
|
|
## 4. Secrets
|
|
|
|
All provider/connector credentials (payment providers, external marketplace connectors, VK/MAX/Telegram bot tokens, FX source keys) live in dedicated secret storage, referenced by opaque `credentialRef` strings in every other contract in this series — never returned in any API response body, never logged in plaintext.
|
|
|
|
## 5. Rate limiting
|
|
|
|
```
|
|
429 response: { error: { code: 'RATE_LIMITED', retryAfterSeconds: number } }
|
|
```
|
|
|
|
Applies to storefront/auth/provider endpoints. Frontend currently has **zero** 429 handling anywhere — see [BACKEND-API-REFERENCE.md §5](../../BACKEND-API-REFERENCE.md) for the full error-envelope contract this should follow.
|
|
|
|
## 6. Step-up authentication
|
|
|
|
Required before: bank/payment detail changes (Phase 5 §5), production launch (Phase 9 §3 step 8), role grants at `PLATFORM_OWNER`/`MARKETPLACE_ADMIN` level, and any manual financial override (refund approval outside normal flow, price override on a live order).
|
|
|
|
## 7. PII minimization
|
|
|
|
Customer/seller PII is exposed only to roles that need it for their scope (e.g. `FINANCE_VIEWER` sees payout totals, not raw bank account numbers unless `FINANCE_MANAGER`+). Export endpoints (`GET .../export`) are themselves audit-logged actions per §3.
|
|
|
|
## 8. What the frontend will start doing once this ships
|
|
|
|
- Route guards and action-level permission checks across the entire backoffice — currently none exist.
|
|
- Backoffice **Audit & Security** section (missing from admin nav today): role changes, sensitive actions, login/security events, exports.
|
|
- Reconcile `AdminRole` (already de-duplicated to one canonical type this session) against the real 17-role table from §1.
|
|
- 429 interceptor + retry-after UI.
|