Cortensor Portal V1 Backend, Data Model, and Gateway Specification

Status

Draft

Purpose

This document is the first implementation-oriented backend reference for Cortensor Portal V1.

It focuses on:

  • what should be stored in Supabase

  • what should be delegated to Unkey

  • what logic belongs in the Portal API gateway/backend

  • how requests should flow from API key to managed Cortensor router nodes

  • how durable usage, request, and billing state should be written

This is a product-backend spec, not a router-node implementation spec.


1. Summary

Portal V1 should be built around a custom Portal backend / gateway that sits between customers and managed Cortensor router pools.

The Portal backend is the product boundary and should own:

  • request authentication

  • model entitlement checks

  • quota interpretation

  • router-pool selection

  • request normalization

  • response normalization

  • usage event emission

  • durable write coordination

The public shape is not:

It is:

The key idea is:

The gateway is the product boundary. It owns authentication, quota, entitlement, routing, and metering semantics, while router nodes remain the backend inference layer.


2. Goals

The backend, durable state, and gateway design should aim to:

  • centralize Cortensor-specific business logic

  • keep the external API stable while the router fleet evolves

  • support quota, entitlement, and routing logic in one owned layer

  • support durable usage and billing write coordination

  • keep customer-facing request behavior productized

  • avoid requiring many raw database reads in the hot path

  • preserve room for future paid plans, credits, and richer routing


3. Scope

In Scope

  • Supabase-backed durable Portal product state

  • Unkey-backed key verification and rate limit support

  • custom Portal backend and request gateway

  • router-pool selection logic

  • request and response normalization

  • durable usage and request logging

  • simple V1 billing foundations

  • basic operational/admin readiness

Out of Scope

  • customer-facing raw router or session control

  • direct exposure of router-node URLs

  • prompt/response retention by default

  • complex billing dimensions on day one

  • advanced autoscaling control plane

  • Kubernetes-native fleet orchestration as a requirement for V1

  • customer-managed sessions


4. Core Backend Shape

Portal V1 should not expose raw router nodes directly to customers.

The public path should be:

Layer Responsibilities

Auth Layer

Owns:

  • user login

  • web session identity

  • auth provider identity bridge

Product Data Layer

Owns:

  • users

  • organizations

  • API key metadata

  • plan and entitlement data

  • usage and billing records

  • router pool metadata

Gateway / Control Plane

Owns:

  • request-time product logic

  • key verification coordination

  • model entitlement checks

  • quota checks

  • routing

  • normalization

  • usage emission

Inference Layer

Owns:

  • router pools

  • router node health

  • actual inference execution

  • dedicated-backed sessions


5. Responsibility Split

5.1 Clerk or Auth Provider

Use Clerk (or the final chosen auth provider) for interactive web app identity.

Auth provider should own:

  • user login

  • email/social/wallet auth if enabled

  • hosted auth UI/session handling

  • auth-provider user ID

  • organization membership if provider-native orgs are used

Auth provider should not be the source of truth for:

  • Portal billing

  • usage state

  • model access policy

  • router pools

  • request logs

Those are Portal-owned product concerns.


5.2 Supabase

Use Supabase as the durable product and control-plane database.

Supabase should store:

  • Portal users

  • organizations

  • memberships

  • API key metadata

  • plans and entitlements

  • model catalog and model access policy

  • quota policy definitions

  • usage events and usage rollups

  • billing ledger

  • router pool metadata

  • request logs

  • operational audit data

Important constraint:

  • Supabase is the source of truth

  • Supabase should not be the only hot-path enforcement dependency for every request

Hot-path fields should be cached or denormalized where practical.


5.3 Unkey

Use Unkey for API key primitives.

Unkey should own or support:

  • API key issuance or key material

  • API key verification

  • revocation-aware validation

  • per-key rate limiting

  • basic key-level analytics

Unkey should not own:

  • model entitlement rules

  • plan semantics

  • billing semantics

  • router pool selection

  • durable usage ledger

  • request normalization

  • response normalization

Unkey is a supporting enforcement layer, not the full product control plane.


5.4 Portal API Gateway / Backend

The Portal backend is required even in V1.

It should own:

  • validating customer API requests

  • calling Unkey to verify API keys

  • loading or caching key/org/product metadata

  • checking model access

  • checking quota allowance

  • resolving product model aliases to router pools

  • selecting a healthy router endpoint inside the chosen pool

  • translating the public API request into router-node request shape

  • translating router-node responses into stable Portal API responses

  • writing usage events and request logs

  • returning consistent errors

This is what makes Portal a product, not just a glue layer.


6. Core Request and Data Flows

6.1 Hosted Inference Request Flow

Recommended public endpoint:

Example public request shape:

Detailed flow:

  1. Gateway receives request.

  2. Gateway generates request_id.

  3. Gateway extracts API key from Authorization: Bearer ....

  4. Gateway verifies key with Unkey.

  5. Gateway loads cached key metadata or looks up api_keys using unkey_key_id.

  6. Gateway confirms organization and key are active.

  7. Gateway validates request shape.

  8. Gateway reads model from request body.

  9. Gateway resolves model_catalog.model_alias.

  10. Gateway checks plan entitlements and model_access_policies.

  11. Gateway applies rate limit through Unkey or fast-state layer.

  12. Gateway checks quota policy for the organization / key.

  13. Gateway resolves model_alias to router_pools.default_router_pool_id.

  14. Gateway selects a healthy router_pool_nodes row.

  15. Gateway transforms the public request into router-node request shape.

  16. Gateway calls the selected Cortensor router node.

  17. Gateway normalizes the router response.

  18. Gateway writes usage_events and request_logs.

  19. Gateway updates async rollups if needed.

  20. Gateway returns normalized response to customer.


6.2 API Key Create Flow

  1. Authenticated user opens create-key flow from Portal UI.

  2. Portal backend verifies:

    • user identity

    • organization membership / ownership context

    • plan allowance (e.g. max active keys)

  3. Portal backend requests key creation through Unkey.

  4. Unkey returns key material / identifier.

  5. Portal backend writes durable metadata into api_keys.

  6. Raw secret is shown once to the user.

  7. Audit event is recorded.

Key point:

  • Portal owns metadata and ownership semantics.

  • Unkey supports issuance and hot-path verification.


6.3 API Key Revoke Flow

  1. Authenticated user requests revoke action.

  2. Portal backend verifies key ownership and account/org authorization.

  3. Portal backend calls Unkey revoke / disable.

  4. Portal backend updates api_keys.status, revoked_at, and revoked_by_user_id.

  5. Audit event is recorded.

  6. UI updates immediately.


6.4 Usage Writeback Flow

After a request completes:

  1. Gateway has:

    • request_id

    • key/org/model context

    • router pool and router node identifiers

    • request outcome

  2. Gateway writes:

    • request_logs

    • usage_events

  3. If needed, async processes later update:

    • usage_rollups

    • billing_ledger

    • derived dashboard summaries

  4. Request tracing remains possible via request_id.

The durable write path should remain Portal-owned even if some writes happen asynchronously.


6.5 Reconciliation Flow (Later-Ready)

Portal should eventually be able to reason about differences between:

  • request accepted by gateway

  • request forwarded to backend

  • inference completed by router

  • usage written durably

V1 does not need perfect reconciliation, but the backend should preserve enough information to reconcile later using:

  • request_id

  • request_logs

  • usage_events

  • router target metadata

  • status and latency fields


The exact schema can evolve, but V1 should start with the following durable tables.

7.1 portal_users

Stores Portal-side user profile data linked to auth.

Suggested fields:

Notes:

  • auth_user_id is the bridge to the chosen auth provider.

  • Keep user profile fields here if Portal needs product-side profile data.

  • Do not store secrets here.


7.2 organizations

Stores account/team ownership.

Suggested fields:

Notes:

  • Even if V1 starts mostly single-user, keep the org/account concept early.

  • API keys should generally belong to an organization or account context, not only a raw user record.


7.3 organization_members

Maps users to organizations.

Suggested fields:

Suggested roles:


7.4 api_keys

Stores Portal metadata for Unkey-backed API keys.

Suggested fields:

Notes:

  • Store only metadata, never the full API key secret.

  • unkey_key_id links Portal metadata to Unkey.

  • masked_key is safe for UI display.

  • status should reflect Portal product state.


7.5 plans

Defines product plans.

Suggested fields:

Example plan codes:


7.6 plan_entitlements

Defines what each plan allows.

Suggested fields:

Example entitlement keys:

Example value:


7.7 model_catalog

Defines product-facing model aliases.

Suggested fields:

Example aliases:

Notes:

  • This is what the public API should expose.

  • Do not expose router hostnames or session IDs as model names.


7.8 model_access_policies

Optional override table for per-org model access.

Suggested fields:

Suggested access values:

Notes:

  • Use this for beta access, allowlists, or emergency model disablement.

  • Plan entitlements define defaults. This table defines overrides.


7.9 quota_windows

Stores durable quota policy windows.

Suggested fields:

Example window_type values:

Notes:

  • For V1, this can support durable visibility and reconciliation.

  • For hot-path enforcement, prefer Unkey / fast-state counters, then write durable events/rollups.


7.10 usage_events

Append-only usage ledger for metering and billing.

Suggested fields:

Notes:

  • This should be append-only where possible.

  • Use request_id for idempotency and tracing.

  • Token fields can remain nullable until backend usage reporting is reliable.


7.11 usage_rollups

Precomputed usage for dashboard speed.

Suggested fields:

Example period_type values:


7.12 billing_ledger

Durable billing/accounting events.

Suggested fields:

Example event types:


7.13 router_pools

Internal metadata for managed router pools.

Suggested fields:

Example pool keys:


7.14 router_pool_nodes

Stores actual managed router endpoints.

Suggested fields:

Notes:

  • base_url is internal and must never be exposed to customer UI/API responses.

  • Status can support:

    • active

    • draining

    • disabled

    • maintenance


7.15 request_logs

Operational request log.

Suggested fields:

Notes:

  • Do not store full prompts/responses by default.

  • If request/response capture is ever needed later, make it explicit, opt-in, and retention-controlled.


7.16 audit_events

Admin and user action trail.

Suggested fields:

Example event types:


8. Gateway Logic Checklist

Before calling a router node, the API gateway should check:

  • API key exists and is valid through Unkey

  • Portal-side key metadata exists

  • key status is active

  • organization status is active

  • requested model exists

  • requested model is active

  • organization plan allows the model

  • organization override policy does not deny the model

  • request is within rate limit

  • request is within quota

  • router pool exists and is active

  • router node exists and is healthy

After router-node response, the gateway should:

  • normalize success response

  • normalize error response

  • record usage event

  • record request log

  • update last-used timestamp for the API key

  • emit metrics/traces


9. Router Node Call Boundary

The gateway should call actual Cortensor router nodes only after product checks pass.

Customer-facing request:

Internal resolution:

The customer should not know:

  • which router node served the request

  • which session served the request

  • how many nodes are in the pool

  • whether a pool is draining or failing over


10. Error Shape

Use stable product errors from the gateway.

Suggested error response:

Suggested codes:

The error surface should remain Portal-owned and productized, not router-native.


11. Hot Path vs Durable Path

Keep the request hot path lean.

Hot Path should prefer

  • Unkey key verification

  • Unkey or fast-state rate limit

  • cached key / org / model / plan metadata

  • router pool health cache

Durable Path should write

  • usage events

  • request logs

  • billing ledger events

  • rollups

  • audit events

If a durable write fails after a successful router response, the gateway should not necessarily fail the customer request. Prefer queue/retry for usage and billing writes once V1 matures.


12. Admin Controls to Plan For

V1 admin/internal tools should eventually support:

  • disable API key

  • disable organization

  • allow / deny model for organization

  • disable model globally

  • drain router pool

  • disable router node

  • inspect request logs

  • inspect usage events

  • grant credits or adjust billing ledger

Not all of these need polished UI on day one, but the backend and data model should be shaped to support them.


13. Implementation Order

Recommended backend build order:

  1. Create Supabase schema for users, organizations, API keys, plans, model catalog, router pools, usage events, and request logs.

  2. Seed free plan, initial model aliases, and initial router pools.

  3. Implement auth sign-in and user/org bootstrap.

  4. Implement API key create/revoke flow with Unkey and api_keys metadata.

  5. Implement read-only usage dashboard from usage_rollups or mocked rollups.

  6. Implement gateway endpoint with Unkey verification.

  7. Add model alias resolution and entitlement checks.

  8. Add router pool selection and router-node forwarding.

  9. Add usage event and request log writes.

  10. Add quota/rate-limit visibility and error messaging.

This sequencing keeps the Portal backend grounded in a working product flow rather than abstract platform work.


14. V1 Non-Goals

Avoid in V1 unless required:

  • exposing raw router-node URLs to customers

  • customer-managed sessions

  • complex billing dimensions

  • full Kubernetes/router autoscaling control plane

  • prompt/response retention by default

  • router topology display in customer UI

The first version should be a productized hosted API, not an infrastructure console.


15. Working Summary

Portal V1 backend should be treated as the owned product control plane for Cortensor Portal.

It exists to coordinate:

  • auth identity

  • key verification

  • durable product/account state

  • model entitlement

  • quota logic

  • router-pool routing

  • request normalization

  • durable usage writes

In one sentence:

The Portal backend and gateway are the product boundary that transform Portal-issued keys and product-level model names into stable, metered requests against managed Cortensor router pools.

Last updated