ENGINEERING SPECS
Traffic Usage and Quota
1. Goals
Traffic usage is an accounting domain, not just observability metrics. It must answer:
- How much traffic a tenant used.
- How much traffic a user used within a tenant.
- How much traffic a subscription used.
- Which node, capability role, runtime binding, endpoint, provider, or region carried the traffic.
- Whether a quota policy should alert, block, or restore access.
Runtime metrics may be exported to Prometheus later. Traffic usage remains in the Control Plane database first because it drives product behavior, quota enforcement, and billing.
2. Accounting Identity
The stable access identity is Subscription.
Tenant
-> User
-> Subscription
-> Endpoint
-> Node
-> RuntimeBinding
Do not use public subscription tokens or protocol secrets as accounting identities:
- subscription tokens rotate.
- Trojan passwords and other protocol credentials rotate.
- subscription IDs remain stable.
Runtime protocol user names use a stable principal key derived from the subscription ID:
om_sub_<subscription_id>
The Control Plane maps that principal back to tenant_id, user_id, and subscription_id.
This prefix is intentionally aligned with the existing OrbitMesh subscription namespace during the MVP, but the value is not a public subscription URL token:
- public subscription token: opaque random token, for example
/subscription/om_sub_<random>. - runtime usage principal: deterministic internal identifier,
om_sub_<subscription_id>. - protocol secret: runtime credential such as a Trojan password.
Do not use the runtime usage principal as an authentication secret. It is only an accounting and stats attribution key.
3. Metering Points
The same packet can be observed at multiple nodes when traffic crosses entry, mesh, relay, and exit roles. Usage records must include a metering point to avoid double counting.
client_access User access side at Traffic Entry. Default source for tenant, user, and subscription quota.
exit_egress Exit side at Traffic Exit. Used for provider cost, region capacity, and supplier reconciliation.
relay_transit Traffic Relay forwarding. Used for path diagnostics and relay capacity planning.
mesh_transit Internal Mesh transit. Used for diagnostics and internal cost analysis.
runtime_local Runtime local management, probes, and control traffic. Used for runtime operations only.
Default quota evaluation consumes only:
metering_point = client_access
Other metering points can be stored and displayed, but must not be added to user quota unless a quota policy explicitly selects them.
Metering points are not capability roles:
capability_role = traffic.entry -> usually reports metering_point = client_access
capability_role = traffic.exit -> usually reports metering_point = exit_egress
capability_role = traffic.relay -> usually reports metering_point = relay_transit
Do not name the metering point traffic_exit or plain egress. The role already carries the Traffic domain prefix; the accounting point should describe where the traffic is measured.
4. Direction Semantics
All usage direction is normalized to the client perspective when metering point is client_access.
upload_bytes client -> endpoint
download_bytes endpoint -> client
total_bytes upload_bytes + download_bytes
For exit_egress, direction is normalized to the exit node perspective:
upload_bytes exit node -> internet or next upstream
download_bytes internet or upstream -> exit node
total_bytes upload_bytes + download_bytes
For relay_transit, direction is normalized to the relay node perspective:
upload_bytes relay node -> next hop
download_bytes previous hop -> relay node
total_bytes upload_bytes + download_bytes
The data model stores upload and download separately. MVP quota policies use total_bytes by default.
5. Runtime Capabilities
Traffic collection is adapter-driven. A runtime adapter declares what it can report:
node_level
capability_binding_level
runtime_binding_level
endpoint_level
access_principal_level
For the MVP:
runtime: sing-box
protocol: trojan
node_level: true
capability_binding_level: true
runtime_binding_level: true
endpoint_level: true
access_principal_level: true
principal_key: om_sub_<subscription_id>
Other protocols and runtimes may only support node-level or runtime-binding-level usage. The Control Plane must not assume every protocol can produce user-level stats.
6. Usage Samples
Traffic usage samples are delta records reported by Edge Runtime.
Recommended logical shape:
traffic_usage_samples
- id
- tenant_id
- user_id nullable
- subscription_id nullable
- node_id
- capability_binding_id nullable
- capability nullable
- role nullable
- runtime_binding_id nullable
- runtime nullable
- endpoint_id nullable
- metering_point
- protocol nullable
- direction
- upload_bytes
- download_bytes
- total_bytes
- window_start
- window_end
- reported_at
- labels_json
Samples are append-only. They should not be deleted or rewritten for manual correction.
7. Rollups
Rollups make Console and quota evaluation cheap.
traffic_usage_rollups
- id
- tenant_id
- user_id nullable
- subscription_id nullable
- node_id nullable
- capability_binding_id nullable
- role nullable
- runtime_binding_id nullable
- endpoint_id nullable
- metering_point
- protocol nullable
- granularity: hour | day | month
- period_start
- period_end
- upload_bytes
- download_bytes
- total_bytes
Rollups can be rebuilt from samples during development. In production they should be maintained by an idempotent aggregation job.
Console uses the current 30-day client access rollup for the Traffic Usage overview. Quota evaluation uses the quota policy period instead of the 30-day overview window.
Current Console behavior:
- scope filter: all, tenant, user, subscription, node.
- target filter: concrete tenant, user, subscription, or node within the selected scope.
- direction filter: all directions or reported runtime direction.
- attribution status: aggregate, attributed, ID-only, or unattributed.
- attribution coverage: user, subscription, and node totals compared with tenant client access total.
- usage tables label
total_bytesas billable total and upload/download fields as raw directional usage. - exceeded disable quotas are displayed as runtime credential blocking; subscription URLs remain accessible.
Target Console behavior:
Usage & Quotasremains the client access accounting and quota page.Node Trafficshowsexit_egress,relay_transit,mesh_transit, andruntime_localusage from the infrastructure perspective.Routing Policiescan show path segment usage when samples include policy and segment attribution.- user quota views must not sum
client_access,exit_egress, andrelay_transittogether.
8. Quota Policies
Quota policies are scoped rules.
quota_policies
- id
- tenant_id
- scope_type: tenant | user | subscription | node | capability_binding | runtime_binding | endpoint
- scope_id nullable
- metering_point
- period: day | month | rolling_30d
- total_bytes_limit nullable
- upload_bytes_limit nullable
- download_bytes_limit nullable
- action: alert | disable
- status
Relevant policies are evaluated together. The effective decision is the strictest blocking result across tenant, user, subscription, node, capability binding, runtime binding, and endpoint scopes.
Current MVP policy scopes exposed in Console:
- tenant.
- user.
- subscription.
- node.
User-scope policies are created from observed user usage. This keeps the MVP UI tied to real accounting identities while user administration is still minimal.
9. Enforcement State
Quota enforcement state is separate from resource lifecycle state.
quota_enforcements
- id
- policy_id
- scope_type
- scope_id
- period_start
- period_end
- used_upload_bytes
- used_download_bytes
- used_total_bytes
- status: normal | exceeded
- exceeded_at
- restored_at
Do not turn quota exceedance into revoked or deleted.
Effective access should be evaluated as:
Subscription.status == active
AND no blocking quota enforcement applies
When a subscription is blocked, the runtime compiler excludes its protocol user from generated runtime configuration and publishes a new desired state.
Console must show the enforcement impact before or during operator action:
alert: record enforcement state only; runtime credentials stay in generated configuration.disablebelow limit: runtime credentials stay active.disableexceeded at tenant scope: affected tenant subscription credential sets can be excluded.disableexceeded at user scope: subscriptions owned by that user can be excluded.disableexceeded at subscription scope: that subscription credential can be excluded.disableexceeded at node scope: the node runtime configuration excludes blocked local traffic entry credentials.
10. Restoration
Quota restoration is driven by evaluation, not by permanent manual state changes.
Restore when:
- a new quota period starts.
- an admin raises the quota above current usage.
- an approved usage adjustment reduces effective usage below the limit.
Manual reset should be represented as an adjustment record, not by deleting usage samples:
usage_adjustments
- id
- tenant_id
- scope_type
- scope_id
- bytes_delta
- reason
- created_by
- created_at
After restoration, the compiler includes the subscription again and publishes a new desired state.
Usage adjustments apply to the selected current quota period. They change the billable total used by quota enforcement and do not rewrite raw upload/download samples.
Console behavior:
- usage row action opens quota adjustment when an active enforcement exists for that scope.
- usage row action pre-fills quota policy creation when no active enforcement exists.
- adjustment history focuses on the selected enforcement scope.
- reset creates a negative adjustment for the current quota period.
11. MVP Execution Plan
- Use
om_sub_<subscription_id>as sing-box Trojan user name. - Enable sing-box local stats collection for supported builds.
- Add Edge Runtime collector that reads counters and persists last counter state locally.
- Report delta samples to the Control Plane.
- Store usage samples in SQL.
- Display tenant, user, subscription, node, runtime binding, and endpoint usage.
- Add quota policies and quota enforcement.
- Filter blocked subscriptions during runtime compilation.
Current implementation status:
- Usage and quota are implemented for
client_access. - sing-box reports node-level
exit_egressandrelay_transitfrom runtime outbound counters when the runtime binding role istraffic.exitortraffic.relay. mesh_transitandruntime_localare target metering points and are not yet fully collected.- Console shows tenant, user, subscription, and node usage.
- Console supports concrete scope target filters.
- Console supports tenant, user, subscription, and node quota policy creation.
- Console links usage rows to quota policy creation or usage adjustment.
- Console shows active policy impact and blocked credential impact.
- Disabled quota policies are not effective.
- The current sing-box collector reads V2Ray user stats for
client_accessand outbound stats for node-levelexit_egress/relay_transit. - The current API schema can store node, runtime binding, capability role, and metering point attribution, but exit and relay reporting must be added at the runtime adapter layer.
12. Non-Goals
MVP does not require:
- real-time hard cutoff inside the runtime before Control Plane confirmation.
- Prometheus as the source of truth for billing.
- per-domain or per-traffic-rule usage.
- exit-side user quota by default.