@xema/omni-protocol 0.1.12 → 0.1.13
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.
- package/dist/index.d.ts +12 -1
- package/dist/index.js +12 -0
- package/dist/testing.js +1 -5
- package/guide.md +12 -3
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -137,7 +137,11 @@ export interface AuthenticationFailure {
|
|
|
137
137
|
}
|
|
138
138
|
/** What a lead may do with their team. Declared by presence. */
|
|
139
139
|
export interface TeamCapabilities {
|
|
140
|
-
/**
|
|
140
|
+
/**
|
|
141
|
+
* This lead may act on their team's breaks through `executeTeamBreak` -- place, release, decide,
|
|
142
|
+
* set policy -- as far as the provider supports; a command it lacks answers
|
|
143
|
+
* `omni.capability-not-enabled`. Requires `executeTeamBreak`.
|
|
144
|
+
*/
|
|
141
145
|
breakControl?: true;
|
|
142
146
|
/** This lead may join a member's call on request. Requires `executeTeamConsult`. */
|
|
143
147
|
consultControl?: true;
|
|
@@ -998,6 +1002,13 @@ export interface BrowserSessionKeyInput {
|
|
|
998
1002
|
taskType: string;
|
|
999
1003
|
browser: TaskBrowser;
|
|
1000
1004
|
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Whether two logins declare the same capabilities, field by field. The comparison an adapter
|
|
1007
|
+
* makes before republishing `authenticated`: capabilities are current, not fixed, and the natural
|
|
1008
|
+
* guard -- comparing the identity -- never fires on a demotion, because the thing that changed is
|
|
1009
|
+
* not the thing being compared. Key order does not matter, and `team: {}` is not `team` absent.
|
|
1010
|
+
*/
|
|
1011
|
+
export declare function sameCapabilities(a: SessionCapabilities, b: SessionCapabilities): boolean;
|
|
1001
1012
|
/**
|
|
1002
1013
|
* The storage-profile key a reusing browser shares, or `undefined` where it shares nothing.
|
|
1003
1014
|
*
|
package/dist/index.js
CHANGED
|
@@ -128,6 +128,18 @@ export const HANDLING_STEPS_WITH_A_PERSON = [
|
|
|
128
128
|
export function handlingStepExpectsAPerson(step) {
|
|
129
129
|
return HANDLING_STEPS_WITH_A_PERSON.includes(step);
|
|
130
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Whether two logins declare the same capabilities, field by field. The comparison an adapter
|
|
133
|
+
* makes before republishing `authenticated`: capabilities are current, not fixed, and the natural
|
|
134
|
+
* guard -- comparing the identity -- never fires on a demotion, because the thing that changed is
|
|
135
|
+
* not the thing being compared. Key order does not matter, and `team: {}` is not `team` absent.
|
|
136
|
+
*/
|
|
137
|
+
export function sameCapabilities(a, b) {
|
|
138
|
+
return a.breaks === b.breaks &&
|
|
139
|
+
(a.team === undefined) === (b.team === undefined) &&
|
|
140
|
+
a.team?.breakControl === b.team?.breakControl &&
|
|
141
|
+
a.team?.consultControl === b.team?.consultControl;
|
|
142
|
+
}
|
|
131
143
|
/**
|
|
132
144
|
* The storage-profile key a reusing browser shares, or `undefined` where it shares nothing.
|
|
133
145
|
*
|
package/dist/testing.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { browserSessionKey, } from "./index.js";
|
|
1
|
+
import { browserSessionKey, sameCapabilities, } from "./index.js";
|
|
2
2
|
import { assertNoViolations, validateAuthenticationState, validateEventEnvelope, validateManifest, validateSnapshot, } from "./validation.js";
|
|
3
3
|
export { ProtocolConformanceError, assertNoViolations } from "./validation.js";
|
|
4
4
|
/**
|
|
@@ -313,10 +313,6 @@ function publishesUserIds(snapshot) {
|
|
|
313
313
|
return false;
|
|
314
314
|
return snapshot.tasks.some(task => Array.isArray(task?.handlingHistory) && task.handlingHistory.some(step => step?.by !== undefined));
|
|
315
315
|
}
|
|
316
|
-
const sameCapabilities = (a, b) => a.breaks === b.breaks &&
|
|
317
|
-
(a.team === undefined) === (b.team === undefined) &&
|
|
318
|
-
a.team?.breakControl === b.team?.breakControl &&
|
|
319
|
-
a.team?.consultControl === b.team?.consultControl;
|
|
320
316
|
/**
|
|
321
317
|
* `refreshing` carries the identity and capabilities of the login it refreshes. A change to
|
|
322
318
|
* either is published as `authenticated`; a different identity is a new login.
|
package/guide.md
CHANGED
|
@@ -1352,7 +1352,7 @@ them from what arrives later.
|
|
|
1352
1352
|
| --- | --- |
|
|
1353
1353
|
| `breaks` | This login may request a break. Requires the four break methods on the connection. |
|
|
1354
1354
|
| `team` | This login leads a team. The provider publishes a `TeamRoster` to it on every snapshot — `[]` when nobody is in it — and to nobody else. |
|
|
1355
|
-
| `team.breakControl` | This lead
|
|
1355
|
+
| `team.breakControl` | This lead may act on their team's breaks through `executeTeamBreak` — place, release, decide, set policy — as far as the provider supports; a command it lacks answers `omni.capability-not-enabled`. Omni asks for a decision only against a member whose `break` is `awaiting-decision`, so a provider that grants on request is never asked to decide. Requires `executeTeamBreak`. |
|
|
1356
1356
|
| `team.consultControl` | This lead may join a member's call on request. Requires `executeTeamConsult`. |
|
|
1357
1357
|
|
|
1358
1358
|
A session action is available only when both the capability and Omni provisioning permit it.
|
|
@@ -1366,7 +1366,10 @@ roster arrives, and nothing for anybody else — and withdraws it on the next re
|
|
|
1366
1366
|
capability goes. A command that arrives after its capability was withdrawn is answered `failed`
|
|
1367
1367
|
with `omni.capability-not-enabled`: the provider names it, so Omni never has to infer from a
|
|
1368
1368
|
capability change it may not have rendered yet that "you are no longer a lead" is the message
|
|
1369
|
-
rather than "that did not work".
|
|
1369
|
+
rather than "that did not work". One trap for adapter authors: the natural guard on a republish
|
|
1370
|
+
compares the identity, and a demotion does not touch it — compare the capabilities, field by
|
|
1371
|
+
field, which is what `sameCapabilities()` does. The thing that changed is not the thing you are
|
|
1372
|
+
comparing, and `assertCapabilityWithdrawal` is the test that catches a guard which never fires.
|
|
1370
1373
|
|
|
1371
1374
|
### Starting authentication
|
|
1372
1375
|
|
|
@@ -3138,6 +3141,12 @@ Use it for every `UserId` — `handlingHistory[].by`, roster members, `memberId`
|
|
|
3138
3141
|
lead command, `ImposedBreak.by`. A bare one is only ever compared against another from the **same** provider; anything
|
|
3139
3142
|
wider goes through this key.
|
|
3140
3143
|
|
|
3144
|
+
### `sameCapabilities(a, b)`
|
|
3145
|
+
|
|
3146
|
+
Whether two logins declare the same capabilities, field by field — key order aside, and with
|
|
3147
|
+
`team: {}` distinct from `team` absent. It is the comparison an adapter makes before republishing
|
|
3148
|
+
`authenticated`, and the one `exerciseAdapter` holds `refreshing` to.
|
|
3149
|
+
|
|
3141
3150
|
## Runtime validation
|
|
3142
3151
|
|
|
3143
3152
|
Structural rules in this document are executable through the runtime validators Omni applies to
|
|
@@ -3233,7 +3242,7 @@ cannot be established from TypeScript structure alone.
|
|
|
3233
3242
|
| Helper | Contract checked |
|
|
3234
3243
|
| --- | --- |
|
|
3235
3244
|
| `assertCapabilityWithdrawal(states, snapshot, manifest)` | A capability withdrawn by a later `authenticated` state is gone from the next snapshot: no roster for a login that no longer leads, no requests for one that may no longer join. Every state is validated on the way, `refreshing` must carry the login over, and the sequence passes only through usable states. |
|
|
3236
|
-
| `assertCommandRefusedAfterWithdrawal(result)` | A command that arrives after its capability was withdrawn fails with `omni.capability-not-enabled`, named by the provider. |
|
|
3245
|
+
| `assertCommandRefusedAfterWithdrawal(result)` | A command that arrives after its capability was withdrawn fails with `omni.capability-not-enabled`, named by the provider. The same assertion serves a command the provider never supported under a capability it declares. |
|
|
3237
3246
|
| `assertReached(result, subjects)` | The exercise met every subject named; throws listing those it did not. Pair it with a clean `exerciseAdapter` result. |
|
|
3238
3247
|
| `assertAuthenticationRestoreAndExpiry(states)` | A restored authenticated session can refresh and ends in expiry. Every state is validated. |
|
|
3239
3248
|
| `assertReconnectWithMissedAssignments(before, reconnect, ids)` | A reconnect snapshot restores assignments received while offline. |
|