# Organization Seat Purchases

> Canonical path: `specs/billing/organization-seat-purchases.md`
> Status: draft-spec
> Scope: AgentTeam-owned organization human-seat purchase plans, prepaid seat
> subscriptions, seat orders, seat payment records, quota calculation, and the
> boundary with MaaS-owned hosted credit billing.

Related canonical specs:

- [Hosted Credits Payment Flow](./hosted-credits-payment.md)
- [Hosted Model Onboarding](./hosted-model-onboarding.md)
- [agentteam-maas Integration Boundary](../maas/agentteam-maas-integration.md)
- `agentteam-maas/specs/maas/service-boundary.md`
- `agentteam-maas/specs/maas/hosted-credit-atomic-units.md`

## Purpose

AgentTeam Paid Center needs a backend purchase flow for organization-level human
seats in billing-enabled commercial deployments. Core self-hosted AgentTeam remains
on the Free entitlement unless an active paid subscription row exists; the paid
checkout surface is enabled by deployment configuration.

This spec defines the durable contract for AgentTeam-owned organization seat billing
and its boundary with MaaS-owned hosted credit billing.

The durable rules are:

- organization seat purchases buy human-user capacity and subscription rights,
  not agent inventory;
- paid human-seat capacity adds to the Free human-seat baseline;
- Free agent capacity is a per-human-owner cap, not an organization-wide shared
  pool;
- Standard and Enterprise subscription agent values are per-human-owner agent
  limits; they are not organization-wide shared agent pools;
- one organization can have at most one current paid seat subscription row and
  at most one active paid tier at a time;
- seat orders are single-action change requests against the current
  subscription and snapshot all price and entitlement facts needed for
  settlement;
- v1 supports one-time Alipay page-pay orders for self-service seat purchases,
  add-ons, upgrades, and manual renewals; it does not support automatic
  recurring payment;
- hosted model credit orders, hosted credit ledgers, hosted payment orders, and
  hosted settlement remain MaaS-owned unless a later canonical MaaS billing spec
  changes that boundary.

## Scope

In scope:

- Organization human-seat plans and per-seat prices.
- The current prepaid organization seat subscription.
- Organization human-seat business orders.
- AgentTeam-owned seat payment records for seat orders.
- Organization human-seat and agent quota calculation.
- Browser-facing Paid Center APIs for seat usage, plan listing, subscription
  state, order creation, order listing/detail, order cancellation, payment
  preparation, payment status sync, and billing history.
- Alipay payment settlement for seat orders in v1.

Out of scope for v1:

- Hosted model credit recharge or hosted model credit business orders in
  AgentTeam-owned seat tables.
- A single checkout or payment order that buys both seats and hosted credits.
- Moving hosted credit payment settlement out of `agentteam-maas`.
- Runtime MaaS routes, MaaS capability issue or refresh routes, or MaaS
  browser-management APIs.
- WeChat Pay, Stripe, bank transfer, offline remittance, saved payment methods,
  automatic renewal, invoices, refunds, and self-service cancellation that
  terminates the current period early.
- Self-service downgrade, seat removal, billing-period change, or cancellation.
- A subscription event ledger or `organization_seat_entitlements` derived cache
  table.
- Organization-list-page billing dependencies. Seat billing works from the
  current workspace's organization.
- Payment history as proof of hosted model entitlement or hosted credit
  availability.
- The future removal or replacement of `AGENTTEAM_BILLING_ENABLED`.

## Terms

| Term | Meaning |
| --- | --- |
| Human seat | A seat for a human organization member. Seat purchases increase human-user capacity or subscription rights. |
| Agent seat | A forbidden concept for this flow. Agents are not purchased as seat inventory. |
| Managed agents per seat | A paid-tier per-human-owner limit. With an active Standard subscription, each human owner can own up to 10 agents; Enterprise subscription allows up to 20. It is not a shared organization pool. |
| Free agent owner limit | The Free-plan per-human-owner maximum number of agents. It is not an organization-wide shared pool. |
| Seat plan | A AgentTeam-owned purchasable tier and per-seat price row for one billing period. |
| Seat subscription | The current or most recent prepaid paid entitlement row for one organization. |
| Seat order | A AgentTeam-owned single-action business order that mutates the seat subscription only after paid settlement. |
| Seat payment order | A AgentTeam-owned provider payment record for one seat order. |
| Hosted credit order | A MaaS-owned hosted credit recharge business order. It is not part of the seat purchase v1 contract. |

## Ownership Boundaries

### AgentTeam-Owned Seat Billing

AgentTeam owns organization human-seat billing:

- `organization_seat_plans`;
- `organization_seat_subscriptions`;
- `organization_seat_orders`;
- `organization_seat_payment_orders`;
- optional AgentTeam-owned seat payment event audit records;
- AgentTeam browser-facing seat billing APIs;
- seat and agent quota calculation from Free constants or the current active
  seat subscription.

`agentteam-maas` must not read or write these tables. Seat billing is not a MaaS
runtime data-plane concern and must not be served from `/maas/v1/*` or
`/internal/maas/v1/*`.

### MaaS-Owned Hosted Credit Billing

`agentteam-maas` owns hosted model credit billing:

- hosted credit recharge orders;
- hosted payment orders and payment events;
- hosted credit grants, batches, transactions, reservations, and settlement;
- hosted billing summary, ledger, payment-history, and pricing read models used
  by AgentTeam through internal service-to-service routes.

AgentTeam may remain the browser-facing hosted billing facade and payment provider
integration point, but hosted credit mutation and settlement must go through the
MaaS internal billing contract. AgentTeam-owned seat payment rows must not become the
source of truth for hosted credit balance, hosted payment settlement, hosted
entitlement, or MaaS runtime availability.

### Checkout And Payment Separation

Paid Center may show seat subscription and hosted credits on the same screen,
but v1 checkout is product-specific:

- a seat order purchases only a seat subscription action;
- a hosted credit recharge order purchases only hosted credits;
- one payment order must not contain both products.

Browser-facing history may compose AgentTeam-owned seat payment rows and MaaS-owned
hosted credit payment rows, but persistence ownership remains separate. Seat
billing tables must not contain strong foreign keys to MaaS hosted credit
tables or to hosted credit business-order tables.

### Organization Quota Source Of Truth

Legacy `organization_plan_assignments`, `plans`, `plan_limits`, and
`organization_plan_limit_overrides` are removed from the application schema.
They are not the paid seat subscription source of truth and must not be used as
a fallback path.

Rules:

- The current paid seat entitlement lives in `organization_seat_subscriptions`.
- Quota checks for human seats and agent creation use the seat entitlement
  resolver defined by this spec regardless of `AGENTTEAM_BILLING_ENABLED`.
- Quota checks enforce the current limited-time Free entitlement: `20` human
  seats and a per-human-owner limit of `10` agents.
- Plan and catalog copy may present the Free baseline as `3` human seats and a
  per-human-owner limit of `5` agents when it also states the limited-time
  expansion to the effective `20`/`10` quota.
- Active paid subscription human capacity is `20 + seat_quantity`.
- Active paid subscription agent capacity is a per-human-owner limit from
  `managed_agents_per_seat_snapshot`, not an organization shared pool.
- Workspaces, machines, and channels are not quota-limited by the billing/plan
  layer.
- Extra human seats and extra per-human-owner agent capacity live in
  `organization_resource_quota_grants`. Human seat grants use
  `metric='seats'` and `quota_scope='organization'`; agent grants use
  `metric='agents'` and `quota_scope='agent_owner'`.
- Grants are additive, positive deltas. They do not create paid subscriptions,
  do not appear as seat order history, and do not prove purchase.
- Historical migrations convert `organization_seat_entitlement_grants` and
  `organization_quota_overrides` rows into the canonical grant ledger. Fresh
  databases do not create those legacy tables. Upgraded databases may retain
  them for compatibility, but runtime quota checks do not read them.

MeshX-managed Memory and Skill repository counts are not seat-plan limited.
Their plan-default rows in `organization_resource_plan_limits` use
`limit_value=-1`, and active `organization_resource_quota_grants` rows for
those metrics do not affect runtime capacity. When billing is enabled, AgentTeam
loads the same unlimited resource decision before creating MeshX resources:

- Free and paid organizations have unlimited Memory and Skill repository
  capacity.
- Browser-originated MeshX Memory and Skill create/fork requests resolve the
  unlimited limit in the AgentTeam API forwarder before proxying to MeshX;
- AgentTeam backend orchestration, such as Role realization that may create Memory
  or Skill resources, resolves the unlimited limit before calling the MeshX
  client;
- MeshX exposes bounded per-owner usage and realization-impact APIs for
  resource facts, but it does not read AgentTeam billing, plan, or grant tables.

## Billing Availability

V1 uses the same billing enablement surface as hosted credit billing. It does
not introduce a seat-specific feature flag.

Any later removal or replacement of `AGENTTEAM_BILLING_ENABLED`, including capability
detection and module-level availability, requires a separate canonical spec.

## Seat Plans

`organization_seat_plans` stores purchasable tier, per-seat price, billing
period, and entitlement facts so business rules are not hard-coded only in
application logic.

Required fields:

- `id`;
- `plan_key`: `team` or `enterprise` for v1 self-service paid seat plans;
- `name`;
- `billing_period`: `month`, `quarter`, or `year`;
- `unit_price_cents`;
- `currency`;
- `managed_agents_per_seat`;
- `min_seat_quantity`;
- `max_seat_quantity`;
- `self_service_enabled`;
- `status`: `active` or `inactive`;
- `metadata_json`;
- `created_at`;
- `updated_at`.

Rules:

- A plan row represents the price for one human seat for one billing period.
- `human_seats_per_unit` and package/bundle pricing are not part of v1.
- The `team` plan key is displayed as Standard subscription. Standard
  self-service purchase allows `1 <= seat_quantity <= 50`.
- Enterprise self-service purchase allows `seat_quantity >= 1`;
  `max_seat_quantity = 0` means no self-service quantity cap.
- Standard subscription uses `managed_agents_per_seat = 10`.
- Enterprise uses `managed_agents_per_seat = 20`.
- Plan changes affect new subscriptions, renewals, and upgrades according to
  the order rules below. Existing subscription periods use their snapshots.
- Field names such as `agent_seats`, `agent_seats_per_unit`, and
  `agent_seats_delta` are forbidden.

## Seat Subscriptions

`organization_seat_subscriptions` stores the current or most recent prepaid
paid entitlement for one organization. It is the paid source of truth for seat
and agent limits.

Required fields:

- `organization_id`, unique;
- `status`: `active`, `expired`, `suspended`, or `cancelled`;
- `plan_key`;
- `billing_period`: `month`, `quarter`, or `year`;
- `seat_quantity`;
- `managed_agents_per_seat_snapshot`;
- `max_human_seats_snapshot`;
- `unit_price_cents_snapshot`;
- `currency`;
- `current_period_start`;
- `current_period_end`;
- `created_at`;
- `updated_at`.

Rules:

- `seat_quantity` stores paid seats only. Total human-seat capacity is
  `free_human_seat_limit + seat_quantity` while the subscription is active.
- An active paid entitlement exists only when `status = active` and
  `current_period_start <= now < current_period_end`.
- Expiry may be derived from time at read time; a background job may later write
  `status = expired`, but quota must not require that job to run first.
- `suspended` is an operator state. It returns quota to Free and does not
  automatically extend the paid period.
- `cancelled` is reserved for future lifecycle flows. V1 self-service does not
  create it.
- One organization must not have concurrent Standard and Enterprise
  subscriptions.
- Historical subscription periods are audited through paid seat orders. V1 does
  not add a separate subscription event ledger.
- Subscription rows are created or updated only by paid seat order settlement in
  v1. Operator manual adjustment of paid subscriptions is out of scope.
- Quota reads use the subscription snapshots, not current plan rows.
- `renew_subscription` refreshes subscription snapshots from the current plan
  after paid settlement.
- `add_seats` in the current period uses the subscription's existing price and
  entitlement snapshots.
- `upgrade_tier` writes the target plan's current price and entitlement facts
  into the subscription after paid settlement.

## Seat Orders

`organization_seat_orders` stores single-action business orders for human-seat
subscription changes. Each order snapshots the full action, price, entitlement,
and proration facts used at creation time.

Required fields:

- `id`;
- `organization_id`;
- `order_type`: `new_subscription`, `add_seats`, `upgrade_tier`, or
  `renew_subscription`;
- `status`: `pending`, `paid`, `cancelled`, `expired`, `failed`, or
  `paid_unapplied`;
- `from_plan_key`;
- `to_plan_key`;
- `billing_period`;
- `seat_quantity_before`;
- `seat_quantity_after`;
- `seat_delta`;
- `current_period_start_snapshot`;
- `current_period_end_snapshot`;
- `unit_price_cents_snapshot`;
- `target_unit_price_cents_snapshot`;
- `base_amount_cents`;
- `proration_snapshot_json`;
- `amount_cents`;
- `currency`;
- `entitlement_snapshot_json`;
- `idempotency_key`;
- `expires_at`;
- `created_by_user_id`;
- `cancelled_by_user_id`;
- `settled_at`;
- `applied_at`;
- `created_at`;
- `updated_at`.

Rules:

- Each order must represent exactly one order type.
- One organization may have at most one not-yet-terminal seat order at a time.
  A pending seat order blocks creating any other seat order until it is paid,
  cancelled, expired, failed, or otherwise terminal.
- Hosted credit recharge orders do not count toward the seat order pending
  limit because they are MaaS-owned and do not mutate the seat subscription.
- V1 does not allow one order to combine `upgrade_tier`, `add_seats`, renewal,
  or billing-period change.
- V1 supports direct `new_subscription` purchase of Standard or Enterprise from
  Free or expired state. Free-to-Enterprise does not need an intermediate
  Standard purchase.
- `new_subscription` upserts the organization's current subscription row when a
  previous expired or inactive row exists.
- `seat_quantity_before` and `seat_quantity_after` store paid seats only, not
  total human-seat capacity.
- V1 supports active Standard to Enterprise upgrade. It does not support
  downgrade.
- V1 supports same-tier add seats in the current period.
- V1 supports renewal of the current tier, current billing period, and current
  `seat_quantity`.
- V1 does not support seat removal, self-service cancellation, or
  billing-period change.
- Pending orders expire after 30 minutes.
- Creating the Alipay page-pay request must set the provider trade timeout to
  the same 30-minute window whenever the provider supports it.
- Settlement must not recalculate `amount_cents` from current plan rows. It
  validates provider amount and currency against the order snapshot.
- Paid settlement applies the subscription mutation exactly once. Replayed paid
  events return the already-applied result.
- If provider payment is confirmed after the local order expiry window and the
  order is no longer safely applicable, the payment fact is retained and the
  seat order moves to `paid_unapplied`. That state does not grant entitlement
  and requires operator handling or refund outside v1.

### Order Type Rules

`new_subscription`:

- allowed when no effective active paid subscription exists;
- `to_plan_key` may be `team` or `enterprise`;
- `seat_quantity_after` must satisfy the current target plan seat range;
- paid settlement sets `current_period_start = settled_at` and
  `current_period_end = add_period(settled_at, billing_period)`.

`add_seats`:

- allowed only for an effective active paid subscription;
- must keep the same `plan_key` and `billing_period`;
- must use the subscription's `unit_price_cents_snapshot`;
- must keep `seat_quantity_after <= max_human_seats_snapshot`;
- does not change `current_period_end`;
- takes effect immediately at `settled_at`.

`upgrade_tier`:

- allowed only for active Standard subscriptions upgrading to Enterprise;
- must keep the same `seat_quantity` and `billing_period`;
- must validate `seat_quantity <= target_plan.max_seat_quantity`;
- computes the source credit from the subscription
  `unit_price_cents_snapshot`;
- computes the target charge from the current Enterprise plan
  `unit_price_cents`;
- does not change `current_period_end`;
- takes effect immediately at `settled_at`.

`renew_subscription`:

- uses the current subscription's `plan_key`, `billing_period`, and
  `seat_quantity`;
- must not change seat quantity;
- validates the current `seat_quantity` against the current plan
  `max_seat_quantity`;
- if the current subscription is still active, paid settlement extends
  `current_period_end` by one billing period;
- if the current subscription is expired, paid settlement starts a new period at
  `settled_at`.

## Proration And Amounts

Amounts are stored as integer currency minor units.

V1 proration uses natural days, not seconds.

Rules:

- Subscription timestamps are stored as UTC timestamps.
- Proration calculations use the organization's timezone. If no organization
  timezone is configured, use UTC.
- The payment creation date counts as a remaining day.
- `remaining_days = days_between(today, current_period_end_date)`.
- `period_days = days_between(current_period_start_date, current_period_end_date)`.
- `prorated_amount_cents = ceil(base_delta_amount_cents * remaining_days /
  period_days)`.
- The order stores `proration_snapshot_json` with timezone, period boundaries,
  remaining days, period days, and formula inputs.
- If the computed amount is zero or below a minimum payable provider amount, the
  order is rejected with `422` and the user must use a supported purchase path.
- Paid settlement does not recalculate proration.

Amount bases:

- `new_subscription`: `seat_quantity_after * current_plan.unit_price_cents`.
- `add_seats`: `seat_delta * subscription.unit_price_cents_snapshot`, prorated
  over the remaining current period.
- `upgrade_tier`:

```text
base_delta_amount_cents =
  seat_quantity *
  (target_unit_price_cents_current - source_unit_price_cents_snapshot)
```

- `renew_subscription`: `seat_quantity * current_plan.unit_price_cents`.

If the `upgrade_tier` base delta is less than or equal to zero, v1 rejects the
self-service order and requires operator handling.

## Seat Payment Orders

`organization_seat_payment_orders` records the one provider payment attempt for
one seat order. V1 is seat-specific; it does not use a generic
`organization_payment_orders` table.

Required fields:

- `id`;
- `organization_id`;
- `seat_order_id`;
- `provider`;
- `provider_order_id`;
- `amount_cents`;
- `currency`;
- `status`: `pending`, `processing`, `paid`, `failed`, or `closed`;
- `paid_at`;
- `closed_at`;
- `raw_payload_json`;
- `created_at`;
- `updated_at`.

Rules:

- V1 `provider` must be `alipay`.
- Each seat order has exactly one seat payment order.
- `provider_order_id` must be unique for provider-facing reconciliation.
- "Continue payment" may return a freshly signed Alipay page-pay URL, but it
  must reuse the same `provider_order_id`.
- Payment amount and currency must match the referenced seat order snapshot.
- Paid settlement must atomically mark the payment order paid, mark the seat
  order paid, and apply the subscription mutation.
- Unpaid close, cancellation, expiry, or failure events must not grant seat
  entitlement.
- `raw_payload_json` may store normalized provider evidence needed for audit,
  but it must not store credentials, private keys, bearer tokens, or unchecked
  request bodies.
- Optional payment event rows may be used for provider event audit and
  deduplication. Paid entitlement idempotency must still be enforced by locking
  and checking the seat order before applying the mutation.

## Alipay Settlement And Cancellation

Seat payments use independent Alipay callback routes from hosted credit
payments:

- `POST /api/billing/seat-orders/alipay/notify`;
- `GET /api/billing/seat-orders/alipay/return`.

Hosted credit routes remain MaaS-owned through the existing hosted credit
contract:

- `POST /api/billing/alipay/notify`;
- `GET /api/billing/alipay/return`.

Rules:

- Notify verifies Alipay signature, app identity, `provider_order_id`, amount,
  currency, and subject before settlement.
- Return is browser convenience only. It must not be treated as trusted
  settlement evidence.
- Return may redirect to the seat order detail and trigger explicit status sync.
- Explicit sync and notify use the same settlement function.
- Paid settlement locks the seat order, payment order, and subscription row.
- If the seat order is already `paid`, settlement returns the current state
  without applying the subscription mutation again.
- Provider paid events with `paid_at <= expires_at` may settle even when notify
  arrives after expiry.
- If provider paid time is absent, settlement uses the server confirmation time
  and records that fallback in the normalized provider evidence.
- Provider paid events with `paid_at > expires_at`, or paid events for orders
  already cancelled/closed/unsafe to apply, move the order to `paid_unapplied`
  and require operator handling.

Cancellation:

- Browser API must provide a cancel action for pending seat orders.
- `POST /api/billing/seat-orders/:orderId/cancel` is the v1 cancel route.
- Cancellation is allowed only for unpaid pending seat orders.
- The backend must close the Alipay trade, or confirm it is already closed,
  before marking the local payment `closed` and seat order `cancelled`.
- If Alipay reports the trade is already paid, cancellation fails and the paid
  settlement path runs or returns the current paid state.
- If provider close fails transiently, the local order remains pending and the
  API reports provider unavailability or conflict.

## Quota Calculation

The effective Free billing entitlement enforced by quota checks is:

```text
free_human_seat_limit = 20
free_agents_per_human_owner_limit = 10
```

For an organization at time `now`:

```text
effective_subscription =
  organization_seat_subscriptions row
  where status = active
    and current_period_start <= now
    and now < current_period_end

if effective_subscription exists:
  human_seat_limit =
    free_human_seat_limit + effective_subscription.seat_quantity
  organization_agent_limit =
    effective_subscription.managed_agents_per_seat_snapshot
else:
  human_seat_limit = free_human_seat_limit
  organization_agent_limit = free_agents_per_human_owner_limit
```

Rules:

- Paid human seats add to the Free human-seat baseline.
- Free and paid agent limits are enforced as per-human-owner caps.
- `max_human_seats` controls purchase legality; it is not a second parallel
  human quota returned beside `human_seat_limit`.
- `managed_agents_per_seat` is enforced per human owner and must not be
  displayed as purchased agent inventory or organization shared capacity.
- Implementations must not compute `agent_limit = free + sum(agent_delta)`.
- Current member count and current agent ownership counts are AgentTeam-owned facts.
  MaaS hosted model credit balance must not affect these seat limits.
- Expiry or suspension returns quota to Free limits.
- Over-quota state must not automatically delete, archive, or disable existing
  organization members or agents.
- When current human members exceed `human_seat_limit`, inviting or joining new
  human members is blocked until the organization renews, upgrades, adds seats,
  or removes members.
- When the machine owner already owns `organization_agent_limit` active agents
  in the organization, that owner cannot create more agents until the
  organization upgrades, an agent grant raises the per-owner limit, or that owner
  archives agents.
- V1 does not interrupt existing agent execution solely because seat billing
  expired or the organization is over quota. Runtime gating requires a separate
  spec.
- Seat usage responses must expose current counts, limits, and over-limit
  booleans.

## Browser API Contract

All browser-facing seat billing routes require the same organization billing
authorization as hosted credit billing:

- authenticated browser session;
- verified identity when email verification is required;
- `X-Workspace-Id` to resolve the current workspace's organization;
- organization `org_owner` or `org_admin` role.

Workspace admins and ordinary members cannot view or mutate seat billing solely
through workspace membership. Public Alipay notify routes do not require a
browser session, but they must verify provider evidence.

The v1 AgentTeam browser-facing API must support:

- organization seat usage and subscription summary for the current workspace's
  organization;
- active seat plan and price listing;
- seat order creation;
- pending seat order listing and order detail;
- returning or regenerating a payment URL for a pending order;
- explicit payment status sync for one order;
- cancelling a pending order;
- seat payment/order history;
- combined billing history across hosted credits and seat subscription
  purchases.

Recommended routes:

- `GET /api/billing/seat-summary`;
- `GET /api/billing/seat-plans`;
- `GET /api/billing/seat-subscription`;
- `GET /api/billing/seat-orders`;
- `POST /api/billing/seat-orders`;
- `GET /api/billing/seat-orders/:orderId`;
- `POST /api/billing/seat-orders/:orderId/sync`;
- `POST /api/billing/seat-orders/:orderId/cancel`;
- `GET /api/billing/history?month=YYYY-MM&product=all|hosted_credit|seat&limit=100`.

Rules:

- Reads and writes must be scoped by `organization_id` and explicit order IDs.
- APIs must not perform broad cross-organization scans for browser requests.
- Browser DTOs live in the API layer. Store models should not carry JSON tags.
- Responses must expose agent limits as per-human-owner limits for both Free
  and paid entitlements.
- UI copy must not use "agent seats", "purchased agent seats", or equivalent
  wording for this flow.
- Pending seat order UI must provide continue payment, sync status, and cancel
  actions.
- Paid, closed, cancelled, expired, failed, and `paid_unapplied` orders must not
  show a cancel action.
- Combined billing history is a bounded browser read model. V1 uses month-bound
  reads and does not require a strict cross-source infinite-scroll cursor.
- For `product=all`, AgentTeam reads a bounded month page from MaaS hosted credit
  billing and a bounded month page from AgentTeam seat billing, merges by time, and
  returns at most the requested limit.
- Combined history rows must include `product_type`, source order ID, provider
  payment ID, status, amount, currency, created time, and paid time when
  present.
- Seat order detail remains product-specific because seat order fields differ
  from hosted credit recharge fields.

## Verification

Minimum implementation verification:

- schema migration and bootstrap schema are updated in AgentTeam;
- seat plan store tests cover active/inactive plans, billing periods, per-seat
  prices, self-service flags, and Standard/Enterprise seat limits;
- subscription tests prove one row per organization, active/expired effective
  status, snapshot usage, and no concurrent active paid tiers;
- seat order tests prove single-action order validation, one pending seat order
  per organization, 30-minute expiry, snapshotting, idempotency keys, order type
  amount formulas, natural-day proration, and no mixed seat/hosted-credit
  checkout;
- quota tests cover Free-only, Standard paid, Enterprise paid, expired paid,
  suspended paid, over-quota existing resources, additive Free/paid human-seat
  capacity, and per-human-owner agent limits;
- payment tests prove Alipay order creation, provider timeout, amount matching,
  paid replay idempotency, return/sync/notify convergence, user cancellation
  with provider close, and `paid_unapplied` behavior;
- API tests prove organization owner/admin authorization, workspace-admin
  denial, organization-scoped reads, no organization-list-page dependency,
  pending order detail/list UI data, and cancel action availability;
- history tests prove hosted credit payment and balance are still served by
  MaaS-owned billing paths, not by AgentTeam seat payment rows, and that combined
  history does not copy MaaS rows into AgentTeam seat tables.

## Acceptance Criteria

- Core self-hosted product behavior keeps the free entitlement unless a paid
  subscription row exists; the paid checkout surface is still controlled by
  deployment configuration.
- Free seat billing usage shows the effective human seat limit `20` and
  per-human-owner agent limit `10`.
- Plan and catalog cards may show the Free baseline `3`/`5` together with
  limited-time expansion copy to `20`/`10`.
- Free and paid organizations do not limit MeshX Memory or MeshX Skill
  repository counts.
- Standard self-service plans allow up to `50` paid human seats and use
  `managed_agents_per_seat = 10` as the per-human-owner agent limit.
- Enterprise self-service plans do not set a self-service human-seat quantity
  cap and use
  `managed_agents_per_seat = 20` as the per-human-owner agent limit.
- One organization cannot have active Standard and Enterprise paid tiers at the
  same time.
- Paid human and agent limits come from the current active seat subscription,
  plus the Free human-seat baseline, not from active paid order summation.
- Seat orders snapshot plan price, subscription state, proration inputs, and
  entitlement facts.
- A seat order and a hosted credit recharge order cannot share one checkout or
  payment order.
- Pending seat orders have an order interface with continue payment, sync, and
  cancel actions.
- Payment history for seat purchases reads AgentTeam-owned
  `organization_seat_payment_orders` scoped to one organization.
- Combined billing history may compose seat and hosted credit rows, but hosted
  model credit recharge continues to use MaaS-owned hosted billing records and
  internal MaaS billing routes.
