Skip to content

Phase 2: Vendor onboarding portal (tenant tokens + billing + attributed devices) #113

@hanwencheng

Description

@hanwencheng

Context

M1 ships the demo; M2 ships the vendor portal that makes the demo a business. Without self-serve onboarding, every vendor pilot requires a manual hand-shake — that doesn't scale beyond 3-5 vendor conversations. The portal converts the demo (the convincing surface) into actual money (the paid pilot).

This issue is the operational backbone of M2 per docs/spec/plans/milestones-roadmap.md §3 — without it, the agent-iam-strategy.md §5 Phase 2 "1 paid pilot at $2-3/device/month" goal is unreachable.

Scope (M2)

Vendor signup flow

  • Email + verification — standard signup, email confirm before any provisioning
  • Stripe + Alipay account binding — vendor connects a payment instrument before they can register devices. Pre-flight check: their account is provisioned + connected before the device-registration API accepts calls.
  • TOS + DPA — operator-visible terms; vendor must accept before tenant activation
  • Branding setup — vendor-side display name, logo (used in audit feed UI and parent-side device list)

Tenant token issuance

  • One Bearer token per vendor, signed by broker (K1). Token format compatible with Phase 1: AgentKeys MCP server — 7 active tools + 3 schema-only #107 MCP server's per-vendor auth.
  • Rotation policy — token validity 90 days; rotation surface in vendor settings; old tokens invalid after rotation grace period (24h)
  • Scope binding — token authorizes ONLY this vendor's actor sub-tree (per-actor isolation per arch.md §17)

Device-registration API

  • Endpoint: POST /v1/vendor/devices/register(device_id, user_omni)
  • Auth: vendor Bearer token + per-request idempotency key
  • Returns: actor_omni for the device, signed binding receipt, suggested cap-policy template
  • Idempotent per CLAUDE.md "Idempotent remote-setup rule" — same (vendor, device_id, user_omni) always returns the same actor_omni

Per-vendor billing dashboard

  • Attributed device count (active in last 30 days), MAU, Pro-tier upgrade revshare (30% of consumer subscriptions per ai-hardware-companion-office-hours.md)
  • Invoice generation — monthly auto-invoice via Stripe; Alipay invoices generated as PDF and emailed (no in-Alipay invoicing API in MVP)
  • Usage details — per-day device count, audit row count (for capacity planning)

Vendor settings page

Pricing

Per docs/research/ai-hardware-companion-office-hours.md:

  • $2-3 / active device / month base fee (active = ≥1 authority event in the trailing 30 days)
  • 30% lifetime acquirer-of-record revshare on consumer Pro upgrades attributed to this vendor

Out of scope (defer)

  • Multi-team accounts within a vendor org (M3 if a vendor asks for it)
  • White-label parent UI per vendor (M4 — branding hooks ship now, full white-label later)
  • Volume discounts / enterprise tier (M4 with first enterprise customer)
  • Self-serve plan changes (M3 — for M2, plan changes go through ops)

Acceptance criteria

  • FoloToy / Ropet / BubblePal (or whichever priority vendor signs first) can self-onboard from a signup page to registering their first device in ≤30 minutes without operator assistance
  • Pilot vendor signs the TOS + connects payment + integrates a device + receives a working actor_omni → demo passes for their hardware
  • Device registration API is idempotent: registering the same (vendor, device_id, user_omni) twice returns the same actor_omni (no duplicate actors)
  • Per-vendor isolation verified: vendor A's Bearer token cannot register a device against vendor B's tenant; vendor A's billing dashboard cannot see vendor B's device count
  • First monthly invoice generated correctly + Stripe webhook integration verified end-to-end on a sandbox account
  • Vendor settings page lets the vendor restrict allowed namespaces; the MCP server (Phase 1: AgentKeys MCP server — 7 active tools + 3 schema-only #107) enforces the restriction via cap-token claims

Risks

Risk Mitigation
Stripe + Alipay dual-rail adds complexity early — pick one for M2? Per ai-hardware-companion-office-hours.md: need Alipay for CN vendors (FoloToy, BubblePal). Skipping Alipay = skipping the wedge market. Ship both; lean on Alipay's PDF-invoice workaround.
Pricing changes after vendor signs → contract disputes TOS includes a 60-day price-change notice clause; price grandfathered for existing pilots
Per-vendor Bearer token leak in vendor's deployed code Document rotation as part of onboarding; emit vendor_token_used_from_new_ip audit row when seen
Idempotency cache exhaustion Idempotency window: 24h. Older keys evict; same key after window returns a NEW actor_omni (acceptable per arch.md actor-binding ceremonies)

References

Effort

~1-2 weeks. Sequencing:

  1. (Days 1-3) Signup + TOS + email verification + Stripe/Alipay account binding
  2. (Days 3-5) Tenant token issuance + scope binding via broker
  3. (Days 5-8) Device registration API + idempotency + binding receipt
  4. (Days 8-10) Billing dashboard + invoice generation
  5. (Days 10-12) Vendor settings + branding + acceptance tests
  6. (Days 12-14) Live pilot integration with first vendor (parallel to Phase 2: FoloToy outbound + first vendor pilot tracking #116)

Pickup notes for the next agent / developer

  • Read milestones-roadmap.md §3 for M2 scope
  • Then ai-hardware-companion-office-hours.md for pricing rationale + Alipay-vs-Stripe verdict
  • Existing broker token issuance lives in crates/agentkeys-broker-server/ — extend, don't replace
  • Stripe integration: use Stripe Connect for marketplace-style billing (we're the platform, vendors are the connected accounts)
  • Alipay integration: Open Platform docs at https://opendocs.alipay.com/; use the Direct Settlement API. PDF invoices are a workaround for missing in-platform invoicing.
  • Don't invent a per-vendor secret-management layer — use the broker's existing K1 signing
  • The device-registration API must be idempotent or vendor SDK retry logic creates duplicate actors. Test this explicitly.
  • Use the /agentkeys-issue-create skill for any follow-up issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/brokerBroker server, cap-token issuance, OIDC issuancearea/uiParent-control UI, vendor onboarding portal, audit dashboard

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions