@opengeni/runtime 4.3.0-canary.36844267522001 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,178 +0,0 @@
1
- # Usage allowances in a product integration
2
-
3
- Use when the product sells included usage, per-seat plans, team budgets,
4
- administrator splits, or top-ups. With the repository available, read
5
- `docs/usage-allowances.md` for complete recipes and
6
- `docs/product-integration.md` for the organization-key/user boundary.
7
- Verify installed SDK types and deployed routes before using these primitives.
8
-
9
- `OPENGENI_USAGE_ALLOWANCES_ENABLED` defaults false for rolling admission.
10
- Upgrade all API/control/turn consumers before enabling new config/grant/rule
11
- writes. Reads and enforcement of persisted policies do not depend on this
12
- producer flag; disabling it is not an allowance bypass or permission to run
13
- old readers.
14
- Disabled producers return 409 for config/grants/non-null member rules;
15
- authorized versioned clear and `rule: null` recovery remain available.
16
-
17
- ## Choose the product policy
18
-
19
- - Per-seat plan: the backend computes included USD micros from paid seats;
20
- `memberDefault: "equal_share"` splits by eligible current OpenGeni members,
21
- not the product's paid-seat count.
22
- - Stable user caps: use `{ credits }`; roster changes and workspace grants do
23
- not automatically expand a fixed member ceiling.
24
- - Team budget: `"monthly"` with default `"none"` gives one workspace ceiling
25
- and no separate member cap. `"none"` as the period is a nonrenewing budget.
26
- - Administrator sliders: turn authenticated choices into `{ share }` rules
27
- with exact member versions. Normalizing the sum is product policy; writes
28
- are per-member, not an atomic roster-wide rebalance.
29
- - Custom shares/top-ups: shares may exceed one or sum above one. They are
30
- ceilings, never reserved allocations or guaranteed access to capacity.
31
-
32
- Amounts are integer USD micros: 1 USD = 1,000,000. Do not use floating dollars,
33
- tokens, or estimated provider expense as allowance amounts.
34
- The configuration is `{ includedCredits, period: "monthly" | "none",
35
- anchorDay?: 1..31, memberDefault?: "none" | "equal_share" | { share } | { credits },
36
- thresholds?: { workspace?: number[], member?: number[] } }`.
37
- Monthly boundaries are UTC, with anchors clamped to each month's last day;
38
- omitted threshold lists default to `[0.8, 1]`.
39
- Each threshold list accepts at most 16 positive fractions up to one.
40
- Anchor edits retain active-window usage until its boundary. Switching to
41
- nonrenewing preserves the accounting key/usage and removes the reset time;
42
- switching back preserves usage and sets a monthly boundary. Use returned
43
- windows rather than computing them from the new config.
44
- Equal shares count canonical eligible humans, including active admitted
45
- external identities and the Personal-workspace owner, never keys/services.
46
-
47
- ## SDK and authority
48
-
49
- The root `OpenGeniClient` provides:
50
-
51
- - `getWorkspaceAllowance(workspaceId)`
52
- - `setWorkspaceAllowance(workspaceId, { ...config, expectedVersion })`
53
- - `clearWorkspaceAllowance(workspaceId, { expectedVersion })`
54
- - `getWorkspaceAllowanceState(workspaceId)` returns `{ version, config }`,
55
- including a cleared lifecycle's version.
56
- - `grantWorkspaceCredits(workspaceId, { operationId, credits, expiresAt? })`
57
- - `setMemberAllowance(workspaceId, subjectId | { source, externalId },
58
- { rule: { share } | { credits } | null, expectedVersion })`
59
- - `getUsage(workspaceId, { period?: "current" | "YYYY-MM", limit?, cursor? })`
60
- - `getMyUsage(workspaceId, { period?: "current" | "YYYY-MM" })`
61
-
62
- Workspace config/grants require a full-access organization key with literal
63
- `api_keys:manage` or verified human `account:admin`; workspace administrators
64
- cannot raise or clear the budget. Human organization budget administration
65
- does not require membership in the target shared workspace, but grants no
66
- operational access or full usage roster.
67
- Member splits require verified human workspace administration or a full
68
- organization key; account-admin-only, workspace-key, and service callers cannot
69
- write them. **All reads and writes refuse agents.** Build authenticated backend/admin flows,
70
- not agent tools that adjust the agent's own spending ceiling.
71
- Membership must already exist; assigning a rule never grants access.
72
-
73
- `expectedVersion: 0` means initial creation, exact versions thereafter.
74
- Store returned versions; refresh/reconcile conflicts rather than guessing.
75
- Member `null` restores the workspace default and is itself versioned.
76
- Clear requires an exact positive version and returns `{ version }`. Supply an
77
- `operationId` and reuse the exact request after a lost response. The replay
78
- rechecks authority and conflicts after a later lifecycle change; read
79
- `getWorkspaceAllowanceState` to reconcile without guessing a version.
80
- The existing configuration read still returns null after clear.
81
- Recreation requires that exact clear version; zero is rejected after any
82
- configuration has existed, including after clear.
83
-
84
- Allowance refusals identify `scope` and `resetsAt`. A workspace ceiling is
85
- raised by an organization administrator/full organization key; a member
86
- ceiling is adjusted by a workspace administrator/full organization key.
87
- Buying organization credits or connecting a subscription does not by itself
88
- raise an exhausted allowance. Web, MCP, and Slack retain this distinction.
89
- Reuse the grant's operation ID and exact body after an uncertain result; a
90
- new ID grants again and a changed body under the same ID conflicts.
91
- Omitted/null expiry means no expiry. A grant increases allowance capacity,
92
- not the organization's purchased-credit balance.
93
- The grant receipt is `{ operationId, credits, remaining, expiresAt }`;
94
- operation IDs are nonblank opaque text bounded to 256 UTF-8 bytes.
95
-
96
- ## Meter and browser boundary
97
-
98
- Usage returns `{ period: { start, end }, workspace, members, nextCursor }`.
99
- Workspace/member rows include `limit`, `used`, `remaining`, `fraction`,
100
- `status: "ok" | "warning" | "exhausted"`, and `resetsAt`; workspace also has
101
- `includedCredits`/`grantsRemaining`, members have subject/external identity,
102
- override `rule`, and `version`. Use returned bounds and computed limits.
103
- Nullable limits/fractions mean unbounded; remaining clamps to zero and
104
- positive-limit fraction can exceed one after settlement. Zero limits report
105
- fraction one and exhausted status even with no recorded usage.
106
- GETs/admission checks are read-only; periodic API maintenance owns snapshots,
107
- rollover, and notification evaluation.
108
-
109
- For the normal browser conversation, use the packaged session proxy and
110
- `client.getMyUsage(...)`. It exposes only `GET /usage/me`, only a `period`
111
- query, and the resolved authenticated user's row through `asUser`. It refuses
112
- full roster/config/grant/member routes and has no service-key fallback.
113
- Render `fraction` instead of raw USD micros; clamp the bar, not the underlying
114
- percentage. The response still contains raw amounts and workspace aggregates:
115
- if those must never reach the browser, provide a same-origin authenticated
116
- server projection returning only allowed fraction/status/reset fields.
117
- Keep the organization key on the backend.
118
-
119
- Share-based ceilings use included credits plus **remaining unexpired grants**,
120
- so they vary with grants, consumption, expiry, and membership. They are not a
121
- promise of a fixed monthly slice.
122
- The workspace meter includes consumed grants from the selected period as well
123
- as remaining grants; the member share base does not. Do not compute member
124
- limits from `workspace.limit`.
125
-
126
- ## Settlement, attribution, and notifications
127
-
128
- Only actual OpenGeni credit debits consume allowance. Externally funded
129
- subscription/BYOK work without such a debit is exempt, not necessarily free
130
- upstream. No reservation occurs: a call may overshoot, concurrent calls may
131
- overshoot together, and the next admission is blocked. Reads remain authorized.
132
- Service work without a verified initiating member uses the workspace ceiling
133
- only. Member schedules, children, goal continuations, and recovery retain their
134
- frozen causal initiating member, never a viewer or guessed session creator.
135
-
136
- `OpenGeniAllowanceExhaustedError` carries `code: "allowance_exhausted"`,
137
- `scope`, `resetsAt`, and optional `subjectId`; it is not an automatic retry.
138
- Accepted messages can encounter asynchronous worker admission refusal; inspect
139
- session state/events rather than resending a prompt.
140
- Session `usage.exhausted` completes a budget-limited turn segment, leaves the
141
- session idle/resumable, and pauses an active goal. A grant/reset is not an
142
- automatic goal resume. Version/grant conflicts return 409; missing targets
143
- 404, unauthorized operations 403, invalid requests 400.
144
- Historical `YYYY-MM` reads select anchor-month counters and the recorded
145
- period configuration/rules/denominator/grant inventory, with expiry evaluated
146
- at period end. Current named periods remain live; identities/row discovery
147
- can still reflect current records, so this is not a complete historical roster.
148
- Settlement time chooses the window; activation does not backfill earlier
149
- ledger usage. Included capacity is spent first, then grants earliest-expiry
150
- first; unused unexpired grants survive a monthly reset. Clearing config is
151
- not a refund or history reset.
152
- Paid Knowledge queries/indexing and warm-compute debits also retain exact
153
- turn/request/enqueue/lease-epoch attribution; observers and creators do not
154
- replace it. Legacy unknown paid attribution can defer/refuse work rather
155
- than silently charge a service. Managed video retains prepaid billing;
156
- matching refunds reverse the original period's recorded usage and exact
157
- included/grant/member allocations once. Expired restored grants stay unusable;
158
- legacy debits without allocation receipts do not get invented reversals.
159
-
160
- The public webhook types are `usage.threshold_reached`,
161
- `usage.exhausted`, and `usage.period_reset`; usage envelopes omit or null
162
- session/turn IDs, have an optional sequence, and carry workspace/member scope
163
- when present. Verify actual deployed
164
- emission and reset timing, not only the type list. Verify signatures with
165
- `verifyWebhookEvent`, dedupe by ID, tolerate unordered at-least-once delivery,
166
- and reread usage after a notification. See `docs/workspace-integrations.md`.
167
- Periodic maintenance in the API webhook-dispatch loop evaluates deduplicated
168
- per-period/member thresholds, idle rollover, and expiry without usage readers
169
- or inference. The exhaustion threshold is always evaluated. Sweeps are bounded
170
- to 20 workspaces/100 members per page by default, normally one minute apart;
171
- reset delivery is not guaranteed at the exact UTC boundary. GETs never enqueue
172
- events. Receipt/outbox enqueue is transactional; maintenance failures are
173
- recorded/retried without reversing earlier debits. Late subscribers are not
174
- guaranteed past threshold replay.
175
-
176
- Verify CAS/replayed grants, UTC month-end windows, fallback rules, expiry,
177
- history, overshoot, frozen attribution, external funding, proxy rejection, and
178
- real webhook emission before presenting a plan as enforced.