Cortensor Portal V1 Detailed Spec 06 - Data Model / Durable State
Status
Draft
Purpose
This document defines the durable Portal-side data model for V1.
Portal V1 should treat Supabase as the durable source of truth for product and account state, while keeping the request hot path from depending on many raw DB reads.
This spec focuses on the durable data layer that supports both:
the customer-facing Portal web app, and
the Portal backend / control plane
1. Summary
Supabase should store the durable Portal-side state needed for:
users
organizations
memberships
API key metadata
plans
entitlements
usage events
request logs
billing ledger
router-pool metadata
This state should support both the dashboard and the control plane.
The key design principle is:
Supabase is the durable source of truth for Portal product state, but not the only hot-path enforcement layer.
2. Goals
The durable Portal-side data model should aim to:
define a practical source of truth for Portal product state
support usage and billing evolution later
keep entity ownership clear
avoid embedding product truth only inside external services
support both user-facing and internal/admin workflows
preserve room for future org, billing, and quota expansion
3. Recommended V1 Entities
Likely core tables:
usersorganizationsorganization_membersapi_keysmodel_access_policiesusage_eventsrequest_logsbilling_ledgerplan_subscriptionsrouter_poolsrouter_pool_models
These tables do not all need to be equally complex in V1, but they define the expected durable shape of the Portal product layer.
4. Users
The users table should anchor the Portal account model.
Suggested responsibilities
auth-provider identity mapping
email or display identity snapshot
created timestamp
status
Notes
The durable users table should represent the Portal-side notion of a user, not just a pass-through auth record.
That allows Portal to own:
account state
activity references
usage relationships
future billing or organization linkage
5. Organizations
If org support is included in V1, keep it simple.
Suggested responsibilities
owning shared API keys later if needed
plan ownership
billing ownership
usage aggregation
Design note
If organizations are deferred in V1, the schema should still be shaped so orgs can be added later without breaking the core model.
That means:
user-owned records should be easy to lift into org-owned records later
ownership fields should be designed with future org support in mind
6. Organization Members
If organizations exist in V1 or shortly after, a membership table should define:
which users belong to which organizations
what role they have
when they joined
whether they are active
Suggested responsibilities
user-to-org relationship
role / permission state
future admin boundaries
future multi-user Portal support
This can remain minimal in V1 if the first version is mostly user-owned.
7. API Keys Table
The api_keys table should hold durable metadata, not raw secrets.
Suggested stored fields
key_idowner_user_idowner_org_idif relevantdisplay_namekey_prefixverification_referenceorkey_hashstatuscreated_atrevoked_atlast_used_atlater if needed
Important rule
The durable table should hold metadata and verification references only.
It should not store reversible raw secrets that can later be re-shown to the user.
Why this table matters
This table supports:
dashboard key management
ownership checks
revoke behavior
account-scoped views
future usage-by-key views
8. Plan Subscriptions
The Portal needs a durable way to express what plan or access tier an account is on.
Suggested responsibilities
current plan name or tier
plan status
plan start / end timestamps if relevant
free-plan vs paid-plan state
future billing linkage
Why this matters
Plan state drives:
usage interpretation
model access
quota rules
future upgrade / downgrade behavior
Even if V1 plan logic is simple, it should still exist as durable state rather than be hardcoded into UI behavior.
9. Model Access Policies
Portal should store model entitlement or access policy in durable state rather than scattering it across UI-only logic.
This allows:
plan-based access control
future model rollout controls
temporary model pause actions
product-facing model catalog rules
Example conceptual uses
free plan may only access certain model aliases
a paid plan may unlock additional model families
certain models may be temporarily disabled without changing frontend code
internal rollout of a new model can be done gradually
This table or policy layer should be interpreted by the Portal backend / control plane.
10. Usage Events
usage_events should provide a durable ledger-like history for:
request acceptance
billable usage
attribution to owner
attribution to model
attribution to plan or rate-limit class
Why usage events matter
Usage events are the raw material for:
usage views
quota accounting
billing rollups
support/debugging
future analytics
Design note
The exact write strategy can evolve, but the ownership should be explicit from the start.
Portal should know:
who consumed usage
on which model
under which key / plan / account context
at what time
11. Request Logs
request_logs can support:
debugging
support workflows
admin inspection
reconciliation
Useful fields may include
request ID
account or org owner
key reference
model alias
router pool chosen
status
created timestamp
latency or completion metadata later if needed
V1 note
Portal V1 should be careful not to overdesign this, but some durable request trace is still useful.
The key is to support:
supportability
debugging
future reconciliation
without building a huge internal observability platform on day one.
12. Billing Ledger
The billing_ledger should exist even if billing is simple in V1.
It should support later evolution toward
credits
subscription allowances
invoice or statement generation
account-level balance history
future model-specific charging rules
V1 design principle
Even if payment / billing is minimal at launch, the Portal should still own a durable accounting-friendly record of billable state transitions.
This prevents billing logic from becoming scattered later.
13. Router Pools
The Portal durable state should know:
which router pools exist
which product models map to which pools
high-level pool status if needed
pool metadata relevant to Portal routing logic
Suggested fields
pool ID
display or internal name
status
capacity class or notes later if needed
created / updated timestamps
This keeps routing decisions owned by the Portal layer rather than hardcoded ad hoc everywhere.
14. Router Pool Models
router_pool_models (or equivalent mapping table) should define:
which product-facing model aliases map to which router pools
Why this matters
Portal users should request:
stable product model names
The Portal backend should then:
resolve those names into router pool targets
This table makes that mapping durable, inspectable, and changeable without rewriting gateway code.
15. Hot-Path Caveat
Supabase should be the durable truth, but not the only hot-path enforcement layer.
The system should avoid:
multiple blocking DB reads per request
slow hot-path entitlement checks
putting volatile counters only in durable storage
Practical interpretation
Durable tables should define the product truth, but request-time checks should rely on:
cache
fast runtime state
precomputed policy views where appropriate
This keeps the request path practical while preserving correctness over time.
16. Ownership & Data Boundaries
One important design goal is to keep ownership clear.
Portal should own the durable truth for
account state
key metadata
entitlement state
usage history
request logs
billing-facing records
router pool product mapping
External systems should not be the only durable owner of product truth
That means:
auth provider should not be the only user record
key vendor should not be the only key truth
gateway-only memory should not be the only usage history
The Portal needs its own durable state layer so it can remain the product system of record.
17. Open Questions
Open questions for later refinement:
how much org support is truly required for V1?
what usage records must be written synchronously?
how much request-log retention is needed at launch?
should model access policies live as normalized tables or simpler product config first?
how much pool-health state belongs in durable DB vs operational runtime systems?
These questions should be resolved with V1 simplicity in mind.
18. Relationship to Other Specs
This spec connects directly to:
02-auth.md03-api-key-management.md04-free-plan-rate-limits-and-gateway.md05-portal-backend-control-plane.md08-usage-metering-and-billing.md09-admin-and-ops.md
The durable data model underpins all of those specs, so this document should be treated as a core support spec for Portal V1.
19. Working Summary
Portal V1 should treat Supabase as the durable source of truth for product and account state.
That durable state should support:
dashboard UX
Portal backend / control-plane logic
usage visibility
request tracing
future billing evolution
router-pool-aware product routing
The main design rule is:
Keep durable product truth inside Portal-controlled storage, while keeping the request hot path fast by avoiding dependence on many raw DB reads per request.
In one sentence:
The Portal V1 data model defines the durable product truth for users, keys, plans, usage, billing, and router-pool mapping, while intentionally keeping hot-path enforcement partly outside raw database reads.
Last updated