@whooshbang/contracts 2.2.0 → 2.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.
- package/CHANGELOG.md +6 -0
- package/contract-manifest.json +32 -32
- package/dist/generated/artifact-index.d.ts +33 -33
- package/dist/generated/artifact-index.js +32 -32
- package/dist/generated/interaction-v1.d.ts +72 -4
- package/dist/generated/validators-standalone.d.ts +492 -480
- package/dist/generated/validators-standalone.js +4191 -2276
- package/dist/generated/validators-standalone.js.map +1 -1
- package/dist/generated/validators.d.ts +2 -1
- package/dist/generated/validators.js +2 -1
- package/dist/generated/validators.js.map +1 -1
- package/dist/generated/whooshbang-v1.d.ts +94 -17
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/interaction-expiry.d.ts +17 -0
- package/dist/interaction-expiry.js +67 -0
- package/dist/interaction-expiry.js.map +1 -0
- package/fixtures/core-v1/fixture-index.json +1 -1
- package/fixtures/core-v1/scenarios/api-credential-invalid-indistinguishable.json +1 -1
- package/fixtures/core-v1/scenarios/api-credential-one-time-reveal.json +1 -1
- package/fixtures/core-v1/scenarios/api-credential-revocation-replay.json +1 -1
- package/fixtures/core-v1/scenarios/api-credential-rotation-overlap.json +1 -1
- package/fixtures/core-v1/scenarios/cancellation-too-late.json +1 -1
- package/fixtures/core-v1/scenarios/cross-organization-project.json +1 -1
- package/fixtures/core-v1/scenarios/cross-project-resource.json +1 -1
- package/fixtures/core-v1/scenarios/environment-mismatch.json +1 -1
- package/fixtures/core-v1/scenarios/idempotency-conflict.json +1 -1
- package/fixtures/core-v1/scenarios/idempotency-equivalent-replay.json +1 -1
- package/fixtures/core-v1/scenarios/malformed-bearer.json +1 -1
- package/fixtures/core-v1/scenarios/metadata-overrun.json +1 -1
- package/fixtures/core-v1/scenarios/missing-scope.json +1 -1
- package/fixtures/core-v1/scenarios/project-create-equivalent-replay.json +1 -1
- package/fixtures/core-v1/scenarios/project-slug-conflict.json +1 -1
- package/fixtures/core-v1/scenarios/provider-outcome-unknown.json +1 -1
- package/fixtures/core-v1/scenarios/subscription-activation-replay.json +1 -1
- package/fixtures/core-v1/scenarios/subscription-authorization-capability-opacity.json +1 -1
- package/fixtures/core-v1/scenarios/subscription-cross-connection-callback-rejected.json +1 -1
- package/fixtures/core-v1/scenarios/subscription-expired-replay.json +1 -1
- package/fixtures/core-v1/scenarios/subscription-selected-connection-replay.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/ack-conflict.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/ack-cross-machine.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/ack-out-of-order.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/ack-replay.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/ambiguous-free-text.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/callback-token-opacity.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/credential-registration-conflict.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/credential-registration-replay.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/credential-revocation-replay.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/credential-rotation.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/first-credential-activates.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/interaction-duplicate.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/interaction-expired.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/interaction-mismatch.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/interaction-retired.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/interaction-stale.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/machine-admin-denied.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/machine-bound-message-create.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/machine-cancel-denied.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/machine-crash-before-ack.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/machine-notifier-mismatch.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/machine-other-message-read.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/machine-owned-message-read.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/machine-subscriber-mismatch.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/poll-uncommitted-cursor-rejected.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/project-credential-machine-endpoint-denied.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/quarantine-integrity-rejected.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/quarantine-signature-rejected.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/quarantine-valid.json +1 -1
- package/fixtures/interaction-machine-v1/scenarios/revoked-machine-credential.json +1 -1
- package/fixtures/recipient-experience-v1/scenarios/membership-broadcast-snapshot.json +1 -1
- package/fixtures/recipient-experience-v1/scenarios/preferred-binding-resolution.json +1 -1
- package/fixtures/recipient-experience-v1/scenarios/recipient-session-security.json +1 -1
- package/fixtures/recipient-experience-v1/scenarios/subscriber-initial-groups-transaction.json +1 -1
- package/openapi/generated/whooshbang-v1.bundle.json +128 -20
- package/openapi/whooshbang-v1.yaml +4 -2
- package/package.json +1 -1
- package/schemas/core-scenario.schema.json +1 -1
- package/schemas/events/agent-binding-degraded-v1.schema.json +1 -1
- package/schemas/events/interaction-expired-v1.schema.json +1 -1
- package/schemas/events/interaction-received-v1.schema.json +1 -1
- package/schemas/events/message-delivered-v1.schema.json +1 -1
- package/schemas/events/message-expired-v1.schema.json +1 -1
- package/schemas/events/message-failed-v1.schema.json +1 -1
- package/schemas/events/message-provider-accepted-v1.schema.json +1 -1
- package/schemas/events/subscription-activated-v1.schema.json +1 -1
- package/schemas/events/subscription-revoked-v1.schema.json +1 -1
- package/schemas/events/whooshbang-event-v1.schema.json +1 -1
- package/schemas/fixture-index.schema.json +1 -1
- package/schemas/interaction-machine-scenario.schema.json +1 -1
- package/schemas/interaction-v1.schema.json +151 -19
- package/schemas/machine-v1.schema.json +1 -1
- package/schemas/provider-capabilities-v1.schema.json +1 -1
- package/schemas/webhooks/webhook-delivery-case-v1.schema.json +1 -1
- package/schemas/webhooks/webhook-signing-vector-v1.schema.json +1 -1
- package/schemas/whooshbang-v1.schema.json +52 -48
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://whooshbang.flowxo.com/schemas/provider-capabilities-v1.schema.json",
|
|
4
|
-
"x-contract-version": "2.
|
|
4
|
+
"x-contract-version": "2.3.0",
|
|
5
5
|
"title": "ProviderCapabilitiesV1",
|
|
6
6
|
"description": "Provider-neutral, renderer-facing delivery and interaction capabilities with explicit degradation.",
|
|
7
7
|
"type": "object",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://whooshbang.flowxo.com/schemas/webhooks/webhook-delivery-case-v1.schema.json",
|
|
4
|
-
"x-contract-version": "2.
|
|
4
|
+
"x-contract-version": "2.3.0",
|
|
5
5
|
"title": "WebhookDeliveryCaseSetV1",
|
|
6
6
|
"description": "Deterministic customer webhook response classification, Retry-After, and delivery-bound cases.",
|
|
7
7
|
"type": "object",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://whooshbang.flowxo.com/schemas/webhooks/webhook-signing-vector-v1.schema.json",
|
|
4
|
-
"x-contract-version": "2.
|
|
4
|
+
"x-contract-version": "2.3.0",
|
|
5
5
|
"title": "WebhookSigningVectorSetV1",
|
|
6
6
|
"description": "Language-neutral deterministic Standard Webhooks V1 verification vectors. All key material is public synthetic test data and must never be used outside fixtures.",
|
|
7
7
|
"type": "object",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://whooshbang.flowxo.com/schemas/whooshbang-v1.schema.json",
|
|
4
|
-
"x-contract-version": "2.
|
|
4
|
+
"x-contract-version": "2.3.0",
|
|
5
5
|
"title": "WhooshBangV1ContractDocument",
|
|
6
6
|
"description": "Public request, resource, summary, and Problem Details models for the WhooshBang V1 REST API.",
|
|
7
7
|
"anyOf": [
|
|
@@ -445,7 +445,7 @@
|
|
|
445
445
|
"type": "integer",
|
|
446
446
|
"minimum": 1,
|
|
447
447
|
"maximum": 50000,
|
|
448
|
-
"description": "A 1-based page number. Present on a response only when the request addressed the list by page rather than by cursor: a cursor walk cannot know which page it is on. What is bounded is the row a page starts at, not the page number: a request whose first row would be past 50,000
|
|
448
|
+
"description": "A 1-based page number. Present on a response only when the request addressed the list by page rather than by cursor: a cursor walk cannot know which page it is on. What is bounded is the row a page starts at, not the page number: a request whose first row would be past 50,000 \u2014 the deepest row any published list ceiling reaches \u2014 is refused as `request_invalid`. Bounding the page number instead would make the last rows of a large list unreachable at a small page size, which is exactly when a person is paging through one."
|
|
449
449
|
},
|
|
450
450
|
"ListPageSize": {
|
|
451
451
|
"type": "integer",
|
|
@@ -457,7 +457,7 @@
|
|
|
457
457
|
"type": "string",
|
|
458
458
|
"minLength": 1,
|
|
459
459
|
"maxLength": 128,
|
|
460
|
-
"pattern": "^[^\u0000-\u001f
|
|
460
|
+
"pattern": "^[^\u0000-\u001f
|
|
461
461
|
"description": "An opaque identifier. Its shape, ordering, and embedded content are not public promises."
|
|
462
462
|
},
|
|
463
463
|
"DiagnosticId": {
|
|
@@ -1907,7 +1907,7 @@
|
|
|
1907
1907
|
"connections:write",
|
|
1908
1908
|
"connections:read"
|
|
1909
1909
|
],
|
|
1910
|
-
"description": "One project-credential capability. Environment authority always comes from the credential record, never a scope or request field. `projects:write` configures the credential's own project and environment; it never creates a project, which remains an organization authority. The project-wide singletons
|
|
1910
|
+
"description": "One project-credential capability. Environment authority always comes from the credential record, never a scope or request field. `projects:write` configures the credential's own project and environment; it never creates a project, which remains an organization authority. The project-wide singletons \u2014 brand, default locale, logo and recipient copy \u2014 are what a live recipient sees, so writing them requires a live credential; a test credential may read them and may write its own environment's policy."
|
|
1911
1911
|
},
|
|
1912
1912
|
"ApiCredentialScopeSet": {
|
|
1913
1913
|
"type": "array",
|
|
@@ -2123,7 +2123,7 @@
|
|
|
2123
2123
|
"connections:write",
|
|
2124
2124
|
"connections:read"
|
|
2125
2125
|
],
|
|
2126
|
-
"description": "One organization-credential capability. `organization:read` is the organization's project directory
|
|
2126
|
+
"description": "One organization-credential capability. `organization:read` is the organization's project directory \u2014 listing the organization's projects and reading one \u2014 and is the only scope here a project credential can never carry; it authorizes nothing below the organization. Every other name is the project-credential vocabulary unchanged, and is exercised only on the environment-scoped routes, where the project and environment come from the path and the credential's authority is the intersection of these scopes with the project-credential vocabulary. An organization credential is therefore never wider than a project credential would have been for the same project environment."
|
|
2127
2127
|
},
|
|
2128
2128
|
"OrganizationCredentialScopeSet": {
|
|
2129
2129
|
"type": "array",
|
|
@@ -2456,7 +2456,7 @@
|
|
|
2456
2456
|
"type": "string",
|
|
2457
2457
|
"minLength": 1,
|
|
2458
2458
|
"maxLength": 100,
|
|
2459
|
-
"pattern": "^[^\u0000-\u001f
|
|
2459
|
+
"pattern": "^[^\u0000-\u001f
|
|
2460
2460
|
},
|
|
2461
2461
|
"asserted_at": {
|
|
2462
2462
|
"$ref": "#/$defs/Timestamp"
|
|
@@ -2542,7 +2542,7 @@
|
|
|
2542
2542
|
"type": "string",
|
|
2543
2543
|
"minLength": 1,
|
|
2544
2544
|
"maxLength": 100,
|
|
2545
|
-
"pattern": "^[^\u0000-\u001f
|
|
2545
|
+
"pattern": "^[^\u0000-\u001f
|
|
2546
2546
|
},
|
|
2547
2547
|
"asserted_at": {
|
|
2548
2548
|
"$ref": "#/$defs/Timestamp"
|
|
@@ -2631,7 +2631,7 @@
|
|
|
2631
2631
|
"type": "string",
|
|
2632
2632
|
"minLength": 1,
|
|
2633
2633
|
"maxLength": 100,
|
|
2634
|
-
"pattern": "^[^\u0000-\u001f
|
|
2634
|
+
"pattern": "^[^\u0000-\u001f
|
|
2635
2635
|
},
|
|
2636
2636
|
"asserted_at": {
|
|
2637
2637
|
"$ref": "#/$defs/Timestamp"
|
|
@@ -2718,7 +2718,7 @@
|
|
|
2718
2718
|
"type": "string",
|
|
2719
2719
|
"minLength": 1,
|
|
2720
2720
|
"maxLength": 100,
|
|
2721
|
-
"pattern": "^[^\u0000-\u001f
|
|
2721
|
+
"pattern": "^[^\u0000-\u001f
|
|
2722
2722
|
},
|
|
2723
2723
|
"asserted_at": {
|
|
2724
2724
|
"$ref": "#/$defs/Timestamp"
|
|
@@ -4356,7 +4356,7 @@
|
|
|
4356
4356
|
"$ref": "#/$defs/Metadata"
|
|
4357
4357
|
},
|
|
4358
4358
|
"interaction": {
|
|
4359
|
-
"$ref": "interaction-v1.schema.json#/$defs/
|
|
4359
|
+
"$ref": "interaction-v1.schema.json#/$defs/InteractionSendRequest"
|
|
4360
4360
|
},
|
|
4361
4361
|
"purpose": {
|
|
4362
4362
|
"enum": ["service", "marketing"],
|
|
@@ -4479,6 +4479,10 @@
|
|
|
4479
4479
|
},
|
|
4480
4480
|
"diagnostic_id": {
|
|
4481
4481
|
"$ref": "#/$defs/DiagnosticId"
|
|
4482
|
+
},
|
|
4483
|
+
"interaction_expires_at": {
|
|
4484
|
+
"$ref": "#/$defs/Timestamp",
|
|
4485
|
+
"description": "Authoritatively resolved answer deadline shared by this broadcast\u2019s interactions, independent of delivery expires_at."
|
|
4482
4486
|
}
|
|
4483
4487
|
},
|
|
4484
4488
|
"additionalProperties": false
|
|
@@ -5398,7 +5402,7 @@
|
|
|
5398
5402
|
"$ref": "#/$defs/Metadata"
|
|
5399
5403
|
},
|
|
5400
5404
|
"interaction": {
|
|
5401
|
-
"$ref": "interaction-v1.schema.json#/$defs/
|
|
5405
|
+
"$ref": "interaction-v1.schema.json#/$defs/InteractionSendRequest"
|
|
5402
5406
|
},
|
|
5403
5407
|
"purpose": {
|
|
5404
5408
|
"enum": ["service", "marketing"],
|
|
@@ -7060,7 +7064,7 @@
|
|
|
7060
7064
|
"minLength": 5,
|
|
7061
7065
|
"maxLength": 32,
|
|
7062
7066
|
"pattern": "^[A-Za-z][A-Za-z0-9_]{1,28}[Bb][Oo][Tt]$",
|
|
7063
|
-
"description": "The @username Telegram's own creation dialog is prefilled with, constrained to Telegram's own rule: 5 to 32 characters, a letter first, letters, digits, and underscores after it, ending in `bot` in any case. The caller proposes it because it is the handle every subscriber sees forever and it cannot be changed once the bot exists
|
|
7067
|
+
"description": "The @username Telegram's own creation dialog is prefilled with, constrained to Telegram's own rule: 5 to 32 characters, a letter first, letters, digits, and underscores after it, ending in `bot` in any case. The caller proposes it because it is the handle every subscriber sees forever and it cannot be changed once the bot exists \u2014 a WhooshBang-generated handle would permanently brand a customer's own bot with our naming, which is the one thing customer-owned modes exist to prevent. It is a suggestion and not a reservation: the administrator can type a different handle into Telegram's dialog, which validates the shape and refuses a handle somebody already holds."
|
|
7064
7068
|
},
|
|
7065
7069
|
"ChannelConnectionStatus": {
|
|
7066
7070
|
"type": "string",
|
|
@@ -7076,7 +7080,7 @@
|
|
|
7076
7080
|
"failed",
|
|
7077
7081
|
"expired"
|
|
7078
7082
|
],
|
|
7079
|
-
"description": "How far a guided setup has reached, which is the only thing a caller can act on while a connection is still `pending`. `awaiting_handoff` waits for the administrator to open the link on the Telegram account that will own the bot; `awaiting_creation` means that Telegram account is bound and the bot does not exist yet; `provisioning` means the bot exists and WhooshBang is installing delivery on it. `failed` and `expired` end the attempt without ending the connection
|
|
7083
|
+
"description": "How far a guided setup has reached, which is the only thing a caller can act on while a connection is still `pending`. `awaiting_handoff` waits for the administrator to open the link on the Telegram account that will own the bot; `awaiting_creation` means that Telegram account is bound and the bot does not exist yet; `provisioning` means the bot exists and WhooshBang is installing delivery on it. `failed` and `expired` end the attempt without ending the connection \u2014 another attempt can be started on the same `pending` connection \u2014 and neither withdraws a bot Telegram has already created, because no provider API can delete one."
|
|
7080
7084
|
},
|
|
7081
7085
|
"HostedChannelConnectionSetupStatus": {
|
|
7082
7086
|
"type": "string",
|
|
@@ -7293,7 +7297,7 @@
|
|
|
7293
7297
|
},
|
|
7294
7298
|
"ChannelConnectionSetup": {
|
|
7295
7299
|
"type": "object",
|
|
7296
|
-
"description": "The unfinished half of a customer-managed connection: what the administrator still has to do, and by when. It is deliberately incapable of carrying a secret. The new bot's token travels from Telegram to WhooshBang server to server, so nothing here is credential material and nothing here references any
|
|
7300
|
+
"description": "The unfinished half of a customer-managed connection: what the administrator still has to do, and by when. It is deliberately incapable of carrying a secret. The new bot's token travels from Telegram to WhooshBang server to server, so nothing here is credential material and nothing here references any \u2014 which is what makes this object safe to poll, render in a dashboard, or hand to whoever is doing the setup.",
|
|
7297
7301
|
"required": [
|
|
7298
7302
|
"status",
|
|
7299
7303
|
"handoff_url",
|
|
@@ -7419,7 +7423,7 @@
|
|
|
7419
7423
|
},
|
|
7420
7424
|
"CustomerApplicationConnectionSetup": {
|
|
7421
7425
|
"type": "object",
|
|
7422
|
-
"description": "The unfinished half of a connection through an application the customer creates and owns: what the owner still has to do at the provider, and by when.\n\nIt is deliberately incapable of carrying a secret. The creation link contains configuration and nothing else, the secrets the owner supplies are write-only and have no field here or on the connection, and the installation grant never travels through a browser at all
|
|
7426
|
+
"description": "The unfinished half of a connection through an application the customer creates and owns: what the owner still has to do at the provider, and by when.\n\nIt is deliberately incapable of carrying a secret. The creation link contains configuration and nothing else, the secrets the owner supplies are write-only and have no field here or on the connection, and the installation grant never travels through a browser at all \u2014 WhooshBang obtains it from the provider's own installation exchange. Everything here is therefore safe to poll, render, and hand to whoever is doing the setup.",
|
|
7423
7427
|
"required": [
|
|
7424
7428
|
"status",
|
|
7425
7429
|
"creation_url",
|
|
@@ -7505,7 +7509,7 @@
|
|
|
7505
7509
|
"type": "string",
|
|
7506
7510
|
"minLength": 1,
|
|
7507
7511
|
"maxLength": 100,
|
|
7508
|
-
"pattern": "^[^\u0000-\u001f
|
|
7512
|
+
"pattern": "^[^\u0000-\u001f
|
|
7509
7513
|
"description": "A sender display name without control characters. It is encoded safely as a structured address field and never accepted as a raw header."
|
|
7510
7514
|
},
|
|
7511
7515
|
"EmailSubjectPolicy": {
|
|
@@ -7585,7 +7589,7 @@
|
|
|
7585
7589
|
"type": "string",
|
|
7586
7590
|
"minLength": 1,
|
|
7587
7591
|
"maxLength": 100,
|
|
7588
|
-
"pattern": "^[^\u0000-\u001f
|
|
7592
|
+
"pattern": "^[^\u0000-\u001f
|
|
7589
7593
|
"description": "A bounded customer description of where consent was collected. The authenticated asserting actor is recorded by the service, never accepted from this object."
|
|
7590
7594
|
},
|
|
7591
7595
|
"asserted_at": {
|
|
@@ -7677,13 +7681,13 @@
|
|
|
7677
7681
|
"type": "string",
|
|
7678
7682
|
"minLength": 1,
|
|
7679
7683
|
"maxLength": 253,
|
|
7680
|
-
"pattern": "^[^\u0000-\u001f
|
|
7684
|
+
"pattern": "^[^\u0000-\u001f
|
|
7681
7685
|
},
|
|
7682
7686
|
"value": {
|
|
7683
7687
|
"type": "string",
|
|
7684
7688
|
"minLength": 1,
|
|
7685
7689
|
"maxLength": 2048,
|
|
7686
|
-
"pattern": "^[^\u0000-\u001f
|
|
7690
|
+
"pattern": "^[^\u0000-\u001f
|
|
7687
7691
|
},
|
|
7688
7692
|
"priority": {
|
|
7689
7693
|
"type": "integer",
|
|
@@ -7713,13 +7717,13 @@
|
|
|
7713
7717
|
"type": "string",
|
|
7714
7718
|
"minLength": 1,
|
|
7715
7719
|
"maxLength": 253,
|
|
7716
|
-
"pattern": "^[^\u0000-\u001f
|
|
7720
|
+
"pattern": "^[^\u0000-\u001f
|
|
7717
7721
|
},
|
|
7718
7722
|
"value": {
|
|
7719
7723
|
"type": "string",
|
|
7720
7724
|
"minLength": 1,
|
|
7721
7725
|
"maxLength": 2048,
|
|
7722
|
-
"pattern": "^[^\u0000-\u001f
|
|
7726
|
+
"pattern": "^[^\u0000-\u001f
|
|
7723
7727
|
},
|
|
7724
7728
|
"status": {
|
|
7725
7729
|
"enum": [
|
|
@@ -7752,7 +7756,7 @@
|
|
|
7752
7756
|
"type": "string",
|
|
7753
7757
|
"minLength": 1,
|
|
7754
7758
|
"maxLength": 100,
|
|
7755
|
-
"pattern": "^[^\u0000-\u001f
|
|
7759
|
+
"pattern": "^[^\u0000-\u001f
|
|
7756
7760
|
},
|
|
7757
7761
|
"instructions_url": {
|
|
7758
7762
|
"type": "string",
|
|
@@ -8190,7 +8194,7 @@
|
|
|
8190
8194
|
"handle": {
|
|
8191
8195
|
"type": "string",
|
|
8192
8196
|
"minLength": 1,
|
|
8193
|
-
"description": "The visible provider handle without a provider-specific sigil
|
|
8197
|
+
"description": "The visible provider handle without a provider-specific sigil \u2014 a bot username, a workspace or app display name, a sender address. Never a credential, installation identifier or provider-native identity reference."
|
|
8194
8198
|
}
|
|
8195
8199
|
},
|
|
8196
8200
|
"allOf": [
|
|
@@ -8312,7 +8316,7 @@
|
|
|
8312
8316
|
},
|
|
8313
8317
|
"HostedChannelConnection": {
|
|
8314
8318
|
"type": "object",
|
|
8315
|
-
"description": "A WhooshBang-owned application installed at one provider authority
|
|
8319
|
+
"description": "A WhooshBang-owned application installed at one provider authority \u2014 a workspace, a tenant, a server \u2014 and referenced by one exact environment connection.",
|
|
8316
8320
|
"required": [
|
|
8317
8321
|
"id",
|
|
8318
8322
|
"project_id",
|
|
@@ -8804,7 +8808,7 @@
|
|
|
8804
8808
|
"additionalProperties": false
|
|
8805
8809
|
},
|
|
8806
8810
|
"CreateChannelConnectionRequest": {
|
|
8807
|
-
"description": "Selects the provider identity this environment will send through, discriminated on `mode`, and naming the provider it is for. The two customer-owned modes differ only in where the bot comes from: `customer_byok` connects one the customer already has, and `customer_managed` has Telegram create a new one on the administrator's own Telegram account. Neither supersedes the other, because a bot that already exists can never be adopted into managed mode
|
|
8811
|
+
"description": "Selects the provider identity this environment will send through, discriminated on `mode`, and naming the provider it is for. The two customer-owned modes differ only in where the bot comes from: `customer_byok` connects one the customer already has, and `customer_managed` has Telegram create a new one on the administrator's own Telegram account. Neither supersedes the other, because a bot that already exists can never be adopted into managed mode \u2014 the manager that may act for a bot is fixed when the bot is created.",
|
|
8808
8812
|
"oneOf": [
|
|
8809
8813
|
{
|
|
8810
8814
|
"type": "object",
|
|
@@ -8819,7 +8823,7 @@
|
|
|
8819
8823
|
"type": "string",
|
|
8820
8824
|
"const": "telegram",
|
|
8821
8825
|
"default": "telegram",
|
|
8822
|
-
"description": "This established setup arm is Telegram-only. Omitted means telegram. A provider whose setup is structurally different
|
|
8826
|
+
"description": "This established setup arm is Telegram-only. Omitted means telegram. A provider whose setup is structurally different \u2014 an OAuth install rather than a credential \u2014 has its own arm of this union rather than bending this one."
|
|
8823
8827
|
},
|
|
8824
8828
|
"display_name": {
|
|
8825
8829
|
"type": "string",
|
|
@@ -8834,7 +8838,7 @@
|
|
|
8834
8838
|
},
|
|
8835
8839
|
{
|
|
8836
8840
|
"type": "object",
|
|
8837
|
-
"description": "Connects a provider identity the customer already owns by supplying its credential.\n\nThis arm carries no identity field, and the absence is deliberate. `provider_identity_digest` is unique across every tenant, so an endpoint that digested a client-supplied identity would answer \"already claimed\" for a bot the caller does not own
|
|
8841
|
+
"description": "Connects a provider identity the customer already owns by supplying its credential.\n\nThis arm carries no identity field, and the absence is deliberate. `provider_identity_digest` is unique across every tenant, so an endpoint that digested a client-supplied identity would answer \"already claimed\" for a bot the caller does not own \u2014 an oracle for whether any given bot is connected to WhooshBang by anyone. The identity is derived server-side from a provider-validated `getMe` on the submitted credential, which no caller can forge without holding the credential itself.",
|
|
8838
8842
|
"required": ["mode", "display_name", "credential"],
|
|
8839
8843
|
"properties": {
|
|
8840
8844
|
"mode": {
|
|
@@ -8845,7 +8849,7 @@
|
|
|
8845
8849
|
"type": "string",
|
|
8846
8850
|
"const": "telegram",
|
|
8847
8851
|
"default": "telegram",
|
|
8848
|
-
"description": "This established setup arm is Telegram-only. Omitted means telegram. A provider whose setup is structurally different
|
|
8852
|
+
"description": "This established setup arm is Telegram-only. Omitted means telegram. A provider whose setup is structurally different \u2014 an OAuth install rather than a credential \u2014 has its own arm of this union rather than bending this one."
|
|
8849
8853
|
},
|
|
8850
8854
|
"display_name": {
|
|
8851
8855
|
"type": "string",
|
|
@@ -8879,7 +8883,7 @@
|
|
|
8879
8883
|
"type": "string",
|
|
8880
8884
|
"const": "telegram",
|
|
8881
8885
|
"default": "telegram",
|
|
8882
|
-
"description": "This established setup arm is Telegram-only. Omitted means telegram. A provider whose setup is structurally different
|
|
8886
|
+
"description": "This established setup arm is Telegram-only. Omitted means telegram. A provider whose setup is structurally different \u2014 an OAuth install rather than a credential \u2014 has its own arm of this union rather than bending this one."
|
|
8883
8887
|
},
|
|
8884
8888
|
"display_name": {
|
|
8885
8889
|
"type": "string",
|
|
@@ -8893,14 +8897,14 @@
|
|
|
8893
8897
|
"type": "string",
|
|
8894
8898
|
"minLength": 1,
|
|
8895
8899
|
"maxLength": 64,
|
|
8896
|
-
"description": "The display name prefilled in the same dialog
|
|
8900
|
+
"description": "The display name prefilled in the same dialog \u2014 what a subscriber reads at the top of the chat, as opposed to the @username they address. Unlike the username this one can be changed afterwards, so it is a convenience rather than a commitment. Omit it and Telegram's dialog opens with no name suggested."
|
|
8897
8901
|
}
|
|
8898
8902
|
},
|
|
8899
8903
|
"additionalProperties": false
|
|
8900
8904
|
},
|
|
8901
8905
|
{
|
|
8902
8906
|
"type": "object",
|
|
8903
|
-
"description": "Starts a guided setup in which the customer creates and owns their own application at the provider. The connection comes back `pending` with an `app_setup` carrying the provider's own creation link, already filled in with this application's configuration where the provider allows it.\n\nThis arm carries no credential field, because at this point no credential exists: the provider issues the application's secrets when the owner creates it. They arrive later through the write-only rotation boundary, and the installation grant never arrives from the caller at all
|
|
8907
|
+
"description": "Starts a guided setup in which the customer creates and owns their own application at the provider. The connection comes back `pending` with an `app_setup` carrying the provider's own creation link, already filled in with this application's configuration where the provider allows it.\n\nThis arm carries no credential field, because at this point no credential exists: the provider issues the application's secrets when the owner creates it. They arrive later through the write-only rotation boundary, and the installation grant never arrives from the caller at all \u2014 WhooshBang obtains it from the provider's installation exchange. The three names here are what the owner's own recipients will see, which is why the caller chooses them rather than WhooshBang: a generated name would permanently brand a customer's own application with ours, and that is the one thing customer-owned modes exist to prevent.\n\nA provider that does not set a connection up this way refuses the request as an unavailable setup mode. Each provider may also refuse a name its own rules do not allow, within the bounds stated here.",
|
|
8904
8908
|
"required": [
|
|
8905
8909
|
"mode",
|
|
8906
8910
|
"provider",
|
|
@@ -8933,7 +8937,7 @@
|
|
|
8933
8937
|
"type": "string",
|
|
8934
8938
|
"minLength": 1,
|
|
8935
8939
|
"maxLength": 80,
|
|
8936
|
-
"description": "The bot display name in the same flow
|
|
8940
|
+
"description": "The bot display name in the same flow \u2014 what a recipient reads at the top of the conversation."
|
|
8937
8941
|
},
|
|
8938
8942
|
"app_description": {
|
|
8939
8943
|
"type": "string",
|
|
@@ -9033,11 +9037,11 @@
|
|
|
9033
9037
|
]
|
|
9034
9038
|
},
|
|
9035
9039
|
"RotateChannelConnectionCredentialRequest": {
|
|
9036
|
-
"description": "Replaces the secret behind a connection, discriminated by where a replacement can come from at all. A customer-owned bot has one only its owner can produce and therefore sends it; a managed bot has one only Telegram can issue and therefore sends nothing. An application the customer owns has separate authorities and names each one it hands over. Either way the connection keeps its provider identity, so a subscriber stays bound to the identity it consented to and only the secret changes.\n\nThe first submission during setup uses this same boundary. Handing a secret over and replacing it are the same operation
|
|
9040
|
+
"description": "Replaces the secret behind a connection, discriminated by where a replacement can come from at all. A customer-owned bot has one only its owner can produce and therefore sends it; a managed bot has one only Telegram can issue and therefore sends nothing. An application the customer owns has separate authorities and names each one it hands over. Either way the connection keeps its provider identity, so a subscriber stays bound to the identity it consented to and only the secret changes.\n\nThe first submission during setup uses this same boundary. Handing a secret over and replacing it are the same operation \u2014 a write that never reads the old value back \u2014 and giving initial setup its own endpoint would have meant two ways to do one thing, differing only in what the connection's status happened to be.",
|
|
9037
9041
|
"oneOf": [
|
|
9038
9042
|
{
|
|
9039
9043
|
"type": "object",
|
|
9040
|
-
"description": "Supplies or replaces the application-specific authorities of an application the customer owns. Every authority that provider's application takes is sent together, both for the first submission during setup and for every later replacement.\n\nSending only the one that changed would read as the kinder API, and it is the wrong shape: the authorities are sealed as one versioned set, so replacing one alone would mean decrypting the others and writing them back
|
|
9044
|
+
"description": "Supplies or replaces the application-specific authorities of an application the customer owns. Every authority that provider's application takes is sent together, both for the first submission during setup and for every later replacement.\n\nSending only the one that changed would read as the kinder API, and it is the wrong shape: the authorities are sealed as one versioned set, so replacing one alone would mean decrypting the others and writing them back \u2014 reading secrets at a boundary whose whole purpose is that nothing reads them.\n\n`application_identity` is safe metadata; the secrets are write-only and are never readable afterwards by any surface. `ingress_secret` is optional in shape because not every provider signs inbound requests with a secret the owner holds; a provider whose application does have one refuses a request that leaves it out, and refuses an `application_identity` that is not in its own format.\n\nThere is no bot-token field here, and the absence is the point: WhooshBang obtains the installation grant from the provider's installation exchange, so it never passes through a browser, a clipboard, this request, or any response.",
|
|
9041
9045
|
"required": [
|
|
9042
9046
|
"provider",
|
|
9043
9047
|
"application_identity",
|
|
@@ -9052,21 +9056,21 @@
|
|
|
9052
9056
|
"minLength": 1,
|
|
9053
9057
|
"maxLength": 128,
|
|
9054
9058
|
"pattern": "^[\\x21-\\x7e]+$",
|
|
9055
|
-
"description": "The identifier the provider issued for the application
|
|
9059
|
+
"description": "The identifier the provider issued for the application \u2014 for Slack, its Client ID. Safe application metadata rather than an authority: it identifies the application in an authorization redirect the provider's users can already see."
|
|
9056
9060
|
},
|
|
9057
9061
|
"application_secret": {
|
|
9058
9062
|
"type": "string",
|
|
9059
9063
|
"minLength": 1,
|
|
9060
9064
|
"maxLength": 512,
|
|
9061
9065
|
"writeOnly": true,
|
|
9062
|
-
"description": "The secret the application authenticates to the provider with
|
|
9066
|
+
"description": "The secret the application authenticates to the provider with \u2014 for Slack, its Client Secret. Write-only: sealed on arrival, never echoed here or by any later read, and reachable only by the exchanges that need it."
|
|
9063
9067
|
},
|
|
9064
9068
|
"ingress_secret": {
|
|
9065
9069
|
"type": "string",
|
|
9066
9070
|
"minLength": 1,
|
|
9067
9071
|
"maxLength": 512,
|
|
9068
9072
|
"writeOnly": true,
|
|
9069
|
-
"description": "The secret that verifies an inbound request really came from the provider
|
|
9073
|
+
"description": "The secret that verifies an inbound request really came from the provider \u2014 for Slack, its Signing Secret. Write-only on the same terms, and reachable only by ingress verification."
|
|
9070
9074
|
}
|
|
9071
9075
|
},
|
|
9072
9076
|
"additionalProperties": false
|
|
@@ -9088,7 +9092,7 @@
|
|
|
9088
9092
|
},
|
|
9089
9093
|
{
|
|
9090
9094
|
"type": "object",
|
|
9091
|
-
"description": "Rotates a `customer_managed` connection, whose replacement only Telegram can issue. Asked to rotate, Telegram revokes the bot's current token and returns the successor to the manager that created it, so there is no customer-supplied credential to send and no field here to send one in
|
|
9095
|
+
"description": "Rotates a `customer_managed` connection, whose replacement only Telegram can issue. Asked to rotate, Telegram revokes the bot's current token and returns the successor to the manager that created it, so there is no customer-supplied credential to send and no field here to send one in \u2014 a caller able to supply one would be describing a bot this mode never handed it. The identity is untouched: the same bot keeps the same @username and the same subscribers, and only the secret behind it is new.",
|
|
9092
9096
|
"required": ["source"],
|
|
9093
9097
|
"properties": {
|
|
9094
9098
|
"source": {
|
|
@@ -9161,7 +9165,7 @@
|
|
|
9161
9165
|
"check_request_url",
|
|
9162
9166
|
"contact_support"
|
|
9163
9167
|
],
|
|
9164
|
-
"description": "The exact safe next action for one test result, in product vocabulary.\n\nIt is a different vocabulary from a connection's own recovery action because the actions genuinely differ: a test that nothing answered is fixed by checking the request URL the provider was given, and a request that arrived and did not verify is fixed by re-entering the app's secrets
|
|
9168
|
+
"description": "The exact safe next action for one test result, in product vocabulary.\n\nIt is a different vocabulary from a connection's own recovery action because the actions genuinely differ: a test that nothing answered is fixed by checking the request URL the provider was given, and a request that arrived and did not verify is fixed by re-entering the app's secrets \u2014 neither of which is a lifecycle transition on the connection.\n\n`check_request_url` is also the honest answer when nobody simply pressed the button: the window closed with nothing arriving, and that has exactly two causes."
|
|
9165
9169
|
},
|
|
9166
9170
|
"ConnectionTestEvidence": {
|
|
9167
9171
|
"type": "object",
|
|
@@ -9171,7 +9175,7 @@
|
|
|
9171
9175
|
"type": "string",
|
|
9172
9176
|
"minLength": 1,
|
|
9173
9177
|
"maxLength": 128,
|
|
9174
|
-
"description": "The visible handle the test went out as
|
|
9178
|
+
"description": "The visible handle the test went out as \u2014 the same identity a subscriber would see."
|
|
9175
9179
|
},
|
|
9176
9180
|
"workspace_display_name": {
|
|
9177
9181
|
"type": "string",
|
|
@@ -9322,7 +9326,7 @@
|
|
|
9322
9326
|
"$ref": "#/$defs/MessageContent"
|
|
9323
9327
|
},
|
|
9324
9328
|
"interaction": {
|
|
9325
|
-
"$ref": "interaction-v1.schema.json#/$defs/
|
|
9329
|
+
"$ref": "interaction-v1.schema.json#/$defs/InteractionSendRequest"
|
|
9326
9330
|
}
|
|
9327
9331
|
},
|
|
9328
9332
|
"allOf": [
|
|
@@ -9371,7 +9375,7 @@
|
|
|
9371
9375
|
},
|
|
9372
9376
|
"CustomerApplicationManifest": {
|
|
9373
9377
|
"type": "object",
|
|
9374
|
-
"description": "The exact configuration an application the customer creates and owns is created from, as data rather than as a URL-encoded blob.\n\nIt exists so the owner can read what they are about to approve, and so a reviewer can check it, without opening the provider. It is built by the provider that owns the format, so `manifest` is that provider's own document and `provider` says whose. It carries configuration only: no organization, project, or environment, no credential, and no provider-native identifier. Any opaque handle inside the request URLs selects candidate setup state and authorizes nothing
|
|
9378
|
+
"description": "The exact configuration an application the customer creates and owns is created from, as data rather than as a URL-encoded blob.\n\nIt exists so the owner can read what they are about to approve, and so a reviewer can check it, without opening the provider. It is built by the provider that owns the format, so `manifest` is that provider's own document and `provider` says whose. It carries configuration only: no organization, project, or environment, no credential, and no provider-native identifier. Any opaque handle inside the request URLs selects candidate setup state and authorizes nothing \u2014 a request still has to carry the provider's own proof over the untouched body before anything inside it is believed.",
|
|
9375
9379
|
"required": [
|
|
9376
9380
|
"provider",
|
|
9377
9381
|
"creation_url",
|
|
@@ -9627,7 +9631,7 @@
|
|
|
9627
9631
|
"type": "string",
|
|
9628
9632
|
"minLength": 1,
|
|
9629
9633
|
"maxLength": 100,
|
|
9630
|
-
"pattern": "^[^\u0000-\u001f
|
|
9634
|
+
"pattern": "^[^\u0000-\u001f
|
|
9631
9635
|
"description": "A bounded customer description of where consent was collected. The authenticated asserting actor is recorded by the service, never accepted from this object."
|
|
9632
9636
|
}
|
|
9633
9637
|
},
|
|
@@ -9666,7 +9670,7 @@
|
|
|
9666
9670
|
"type": "string",
|
|
9667
9671
|
"minLength": 1,
|
|
9668
9672
|
"maxLength": 100,
|
|
9669
|
-
"pattern": "^[^\u0000-\u001f
|
|
9673
|
+
"pattern": "^[^\u0000-\u001f
|
|
9670
9674
|
"description": "A bounded customer description of the service relationship. The authenticated asserting actor is recorded by the service, never accepted from this object."
|
|
9671
9675
|
},
|
|
9672
9676
|
"basis": {
|
|
@@ -9733,7 +9737,7 @@
|
|
|
9733
9737
|
},
|
|
9734
9738
|
"SharedEmailStatus": {
|
|
9735
9739
|
"type": "object",
|
|
9736
|
-
"description": "Safe state of the exact shared sender generation and this organization
|
|
9740
|
+
"description": "Safe state of the exact shared sender generation and this organization\u2019s domain hold. It conveys no recipient consent and never authorizes fallback.",
|
|
9737
9741
|
"required": [
|
|
9738
9742
|
"sender_generation",
|
|
9739
9743
|
"sender_state",
|
|
@@ -11641,7 +11645,7 @@
|
|
|
11641
11645
|
"$ref": "#/$defs/Metadata"
|
|
11642
11646
|
},
|
|
11643
11647
|
"interaction": {
|
|
11644
|
-
"$ref": "interaction-v1.schema.json#/$defs/
|
|
11648
|
+
"$ref": "interaction-v1.schema.json#/$defs/InteractionSendRequest"
|
|
11645
11649
|
},
|
|
11646
11650
|
"purpose": {
|
|
11647
11651
|
"enum": ["service", "marketing"],
|
|
@@ -11732,7 +11736,7 @@
|
|
|
11732
11736
|
},
|
|
11733
11737
|
"OperatorPreferences": {
|
|
11734
11738
|
"type": "object",
|
|
11735
|
-
"description": "The authenticated person
|
|
11739
|
+
"description": "The authenticated person\u2019s own destinations and preferred channel in this project. Shared credentials cannot manage a human\u2019s preferences.",
|
|
11736
11740
|
"required": ["operator", "settings", "connections"],
|
|
11737
11741
|
"properties": {
|
|
11738
11742
|
"operator": {
|
|
@@ -11768,7 +11772,7 @@
|
|
|
11768
11772
|
},
|
|
11769
11773
|
"OperatorConnectRequest": {
|
|
11770
11774
|
"type": "object",
|
|
11771
|
-
"description": "Connect the signed-in person
|
|
11775
|
+
"description": "Connect the signed-in person\u2019s own destination through a configured channel. This never changes another person\u2019s channels.",
|
|
11772
11776
|
"required": ["connection_id", "channel"],
|
|
11773
11777
|
"properties": {
|
|
11774
11778
|
"connection_id": {
|