Skip to documentation
OrbitMeshDocs
Browse documentation
Docs/Engineering Specs

ENGINEERING SPECS

Traffic Usage and Quota

Traffic usage is an accounting domain, not just observability metrics. It must answer:
View source

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_bytes as 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 & Quotas remains the client access accounting and quota page.
  • Node Traffic shows exit_egress, relay_transit, mesh_transit, and runtime_local usage from the infrastructure perspective.
  • Routing Policies can show path segment usage when samples include policy and segment attribution.
  • user quota views must not sum client_access, exit_egress, and relay_transit together.

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.
  • disable below limit: runtime credentials stay active.
  • disable exceeded at tenant scope: affected tenant subscription credential sets can be excluded.
  • disable exceeded at user scope: subscriptions owned by that user can be excluded.
  • disable exceeded at subscription scope: that subscription credential can be excluded.
  • disable exceeded 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

  1. Use om_sub_<subscription_id> as sing-box Trojan user name.
  2. Enable sing-box local stats collection for supported builds.
  3. Add Edge Runtime collector that reads counters and persists last counter state locally.
  4. Report delta samples to the Control Plane.
  5. Store usage samples in SQL.
  6. Display tenant, user, subscription, node, runtime binding, and endpoint usage.
  7. Add quota policies and quota enforcement.
  8. Filter blocked subscriptions during runtime compilation.

Current implementation status:

  • Usage and quota are implemented for client_access.
  • sing-box reports node-level exit_egress and relay_transit from runtime outbound counters when the runtime binding role is traffic.exit or traffic.relay.
  • mesh_transit and runtime_local are 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_access and outbound stats for node-level exit_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.
OrbitMesh DocumentationContent follows the repository's main branch.