@company-semantics/contracts 92.0.0 → 93.1.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/package.json +13 -12
- package/src/__tests__/resource-keys.test.ts +1 -0
- package/src/action-items/README.md +12 -4
- package/src/action-items/schemas.ts +10 -0
- package/src/affordances/README.md +52 -1
- package/src/affordances/__tests__/README.md +10 -1
- package/src/affordances/__tests__/affordances.test.ts +13 -1
- package/src/affordances/__tests__/catalog-wave.test.ts +237 -0
- package/src/affordances/affordance.ts +56 -4
- package/src/affordances/args.ts +44 -1
- package/src/affordances/available.ts +59 -0
- package/src/affordances/coverage.ts +51 -0
- package/src/affordances/ids.ts +28 -0
- package/src/affordances/index.ts +17 -0
- package/src/api/README.md +1 -0
- package/src/api/generated-spec-hash.ts +2 -2
- package/src/api/generated.ts +506 -1
- package/src/api/primitives.ts +13 -0
- package/src/billing/README.md +1 -0
- package/src/billing/refusals.ts +12 -0
- package/src/chat/__tests__/page-context.test.ts +22 -43
- package/src/chat/__tests__/runtime-profile.test.ts +20 -44
- package/src/generated/openapi-routes.ts +1 -0
- package/src/message-parts/README.md +5 -0
- package/src/message-parts/affordance-offer.ts +44 -0
- package/src/message-parts/index.ts +7 -0
- package/src/message-parts/types.ts +7 -1
- package/src/message-parts/wire.ts +18 -0
- package/src/notifications/README.md +17 -3
- package/src/notifications/__tests__/README.md +4 -0
- package/src/notifications/__tests__/__snapshots__/render-snapshot.test.ts.snap +27 -25
- package/src/notifications/__tests__/fixtures.ts +7 -1
- package/src/notifications/__tests__/grounded-ctas.test.ts +103 -0
- package/src/notifications/__tests__/render-snapshot.test.ts +1 -1
- package/src/notifications/content.ts +9 -0
- package/src/notifications/kinds/billing-auto-recharge-failed.ts +4 -2
- package/src/notifications/kinds/billing-payment-past-due.ts +2 -0
- package/src/notifications/kinds/billing-suspended.ts +2 -0
- package/src/notifications/kinds/chat-shared.ts +10 -3
- package/src/notifications/kinds/company-md-access-approved.ts +13 -6
- package/src/notifications/kinds/share-granted.ts +1 -1
- package/src/notifications/kinds/unit-owner-granted.ts +9 -2
- package/src/notifications/payloads.ts +6 -0
- package/src/proactive/README.md +18 -2
- package/src/proactive/__tests__/README.md +11 -1
- package/src/proactive/__tests__/chat-templates.test.ts +7 -6
- package/src/proactive/__tests__/proactive-offers.test.ts +124 -0
- package/src/proactive/__tests__/vocabulary.test.ts +1 -1
- package/src/proactive/composer.ts +11 -0
- package/src/proactive/templates/README.md +11 -3
- package/src/proactive/templates/billing-auto-recharge-failed.ts +1 -0
- package/src/proactive/templates/billing-balance-exhausted.ts +2 -6
- package/src/proactive/templates/billing-payment-past-due.ts +1 -0
- package/src/proactive/templates/billing-subscription-canceled.ts +1 -5
- package/src/proactive/templates/billing-suspended.ts +1 -0
- package/src/proactive/templates/morning-brief.ts +1 -0
- package/src/proactive/templates/org-became-shared.ts +4 -3
- package/src/proactive/templates/source-sync-review-ready.ts +3 -8
- package/src/proactive/templates/workflow-needs-attention.ts +1 -0
- package/src/rate-limit/README.md +27 -1
- package/src/rate-limit/__tests__/README.md +23 -0
- package/src/rate-limit/__tests__/rate-limited-error.test.ts +53 -0
- package/src/rate-limit/index.ts +33 -0
- package/src/resource-key-tables.ts +1 -0
- package/src/resource-key-types.ts +3 -0
- package/src/resource-keys.ts +1 -0
- package/src/root-exports/agent-runtime.ts +14 -2
- package/src/root-exports/delivery.ts +15 -0
|
@@ -47,11 +47,7 @@ export const billingSubscriptionCanceledComposer: ProactiveChatComposer<"billing
|
|
|
47
47
|
prompt:
|
|
48
48
|
"What happens to the AI funds already in my wallet after cancellation?",
|
|
49
49
|
},
|
|
50
|
-
{
|
|
51
|
-
id: "resubscribe",
|
|
52
|
-
label: "How do I resubscribe?",
|
|
53
|
-
prompt: "How do I start the seat subscription again?",
|
|
54
|
-
},
|
|
55
50
|
],
|
|
51
|
+
affordances: [{ id: "billing.open" }],
|
|
56
52
|
}),
|
|
57
53
|
};
|
|
@@ -74,9 +74,9 @@ export const orgBecameSharedComposer: ProactiveChatComposer<"orgBecameShared"> =
|
|
|
74
74
|
text:
|
|
75
75
|
`${openingFor(facts)}\n\n` +
|
|
76
76
|
`This is a relocation, not an addition: Integrations, Invite team ` +
|
|
77
|
-
`members, AI usage, Spending controls and Billing have moved
|
|
78
|
-
`
|
|
79
|
-
`belong to the workspace rather than to you.`,
|
|
77
|
+
`members, AI usage, Spending controls and Billing have moved from your ` +
|
|
78
|
+
`own area to the workspace's. Nothing was removed — the five sections ` +
|
|
79
|
+
`now belong to the workspace rather than to you.`,
|
|
80
80
|
replies: [
|
|
81
81
|
{
|
|
82
82
|
id: "plain-english",
|
|
@@ -96,5 +96,6 @@ export const orgBecameSharedComposer: ProactiveChatComposer<"orgBecameShared"> =
|
|
|
96
96
|
prompt: "Who can see what in my workspace now that it is shared?",
|
|
97
97
|
},
|
|
98
98
|
],
|
|
99
|
+
affordances: [{ id: "workspace.openOrgSettings" }],
|
|
99
100
|
}),
|
|
100
101
|
};
|
|
@@ -36,17 +36,11 @@ export const sourceSyncReviewReadyComposer: ProactiveChatComposer<"sourceSyncRev
|
|
|
36
36
|
`strategy documents and have proposed changes for you to ` +
|
|
37
37
|
`review.\n\n` +
|
|
38
38
|
`Nothing has been changed. Each document is updated only when ` +
|
|
39
|
-
`you say so, as an ordinary version
|
|
39
|
+
`you say so, as an ordinary version that can be restored, and ` +
|
|
40
40
|
`anything a person has edited is left alone unless you choose ` +
|
|
41
41
|
`otherwise.`) +
|
|
42
|
-
`\n\
|
|
43
|
-
`nothing happens.`,
|
|
42
|
+
`\n\nThe review waits for you. If you leave it, nothing happens.`,
|
|
44
43
|
replies: [
|
|
45
|
-
{
|
|
46
|
-
id: "open-review",
|
|
47
|
-
label: "Open the review",
|
|
48
|
-
prompt: "Open the source review.",
|
|
49
|
-
},
|
|
50
44
|
{
|
|
51
45
|
id: "what-was-found",
|
|
52
46
|
label: "What did you find?",
|
|
@@ -60,5 +54,6 @@ export const sourceSyncReviewReadyComposer: ProactiveChatComposer<"sourceSyncRev
|
|
|
60
54
|
"If I attach a source to a document, who will be able to see it?",
|
|
61
55
|
},
|
|
62
56
|
],
|
|
57
|
+
affordances: [],
|
|
63
58
|
}),
|
|
64
59
|
};
|
package/src/rate-limit/README.md
CHANGED
|
@@ -35,6 +35,29 @@ interface RateLimitResult {
|
|
|
35
35
|
}
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
### RateLimitedErrorResponseSchema
|
|
39
|
+
|
|
40
|
+
The 429 body every rate-limited response carries — exactly what backend's
|
|
41
|
+
shared limiter sends, plus the reset fact:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
{
|
|
45
|
+
error: "RATE_LIMIT_EXCEEDED"; // RATE_LIMITED_ERROR_CODE
|
|
46
|
+
scope?: "email" | "ip" | "global";
|
|
47
|
+
message: string;
|
|
48
|
+
retryAfterSeconds: number | null; // whole seconds until the window resets
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The object is strict and `retryAfterSeconds` is REQUIRED: it mirrors the
|
|
53
|
+
`Retry-After` header, or is null when the limiter cannot say.
|
|
54
|
+
|
|
55
|
+
**Facts only.** `retryAfterSeconds` is a fact, so the message states it
|
|
56
|
+
("Too many requests. Available in 30s.") and never tells the reader to retry.
|
|
57
|
+
A retry control, if a surface has one, is that surface's own control label
|
|
58
|
+
(control ADR affordance-system). Distinct from `ShedResponse` in
|
|
59
|
+
`src/pressure.ts`, which is the load-shed body only.
|
|
60
|
+
|
|
38
61
|
## Semantic Convention
|
|
39
62
|
|
|
40
63
|
This domain uses `allowed: boolean` where `true` means the request is permitted.
|
|
@@ -54,9 +77,12 @@ This is the canonical semantic across all Company Semantics repos.
|
|
|
54
77
|
|
|
55
78
|
## Public API
|
|
56
79
|
|
|
80
|
+
- `RATE_LIMITED_ERROR_CODE`
|
|
57
81
|
- `RateLimitConfig` _(type)_
|
|
58
82
|
- `RateLimitResult` _(type)_
|
|
59
83
|
- `RateLimitTier`
|
|
84
|
+
- `RateLimitedErrorResponse` _(type)_
|
|
85
|
+
- `RateLimitedErrorResponseSchema`
|
|
60
86
|
|
|
61
87
|
<!-- END GENERATED: readme-public-api -->
|
|
62
88
|
|
|
@@ -70,6 +96,6 @@ _None._
|
|
|
70
96
|
|
|
71
97
|
**External packages:**
|
|
72
98
|
|
|
73
|
-
|
|
99
|
+
- `zod`
|
|
74
100
|
|
|
75
101
|
<!-- END GENERATED: readme-dependencies -->
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# rate-limit/\_\_tests\_\_/
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Locks the shape of the rate-limited error envelope.
|
|
6
|
+
|
|
7
|
+
- `rate-limited-error.test.ts` — proves a rate-limited body carries
|
|
8
|
+
`retryAfterSeconds` as whole non-negative seconds or null and is refused
|
|
9
|
+
without it, refuses any code other than `RATE_LIMIT_EXCEEDED`, and that the
|
|
10
|
+
schema and code are reachable from the package root as the same binding.
|
|
11
|
+
|
|
12
|
+
## Invariants
|
|
13
|
+
|
|
14
|
+
- These assert VOCABULARY and SHAPE, never limiter behavior. Window sizes and
|
|
15
|
+
which routes are limited belong to backend.
|
|
16
|
+
|
|
17
|
+
## Public API
|
|
18
|
+
|
|
19
|
+
None — test-only.
|
|
20
|
+
|
|
21
|
+
## Dependencies
|
|
22
|
+
|
|
23
|
+
`vitest`, `../index` and the package root.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import * as root from "../../index";
|
|
4
|
+
import {
|
|
5
|
+
RATE_LIMITED_ERROR_CODE,
|
|
6
|
+
RateLimitedErrorResponseSchema,
|
|
7
|
+
} from "../index";
|
|
8
|
+
|
|
9
|
+
const body = (fields: Record<string, unknown>) => ({
|
|
10
|
+
error: "RATE_LIMIT_EXCEEDED",
|
|
11
|
+
message: "Too many requests.",
|
|
12
|
+
...fields,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe("the rate-limited error envelope", () => {
|
|
16
|
+
it("a rate-limited body states when the window resets, or null", () => {
|
|
17
|
+
expect(
|
|
18
|
+
RateLimitedErrorResponseSchema.safeParse(body({ retryAfterSeconds: 30 }))
|
|
19
|
+
.success,
|
|
20
|
+
).toBe(true);
|
|
21
|
+
expect(
|
|
22
|
+
RateLimitedErrorResponseSchema.safeParse(
|
|
23
|
+
body({ retryAfterSeconds: null }),
|
|
24
|
+
).success,
|
|
25
|
+
).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("refuses a rate-limited body without retryAfterSeconds", () => {
|
|
29
|
+
expect(RateLimitedErrorResponseSchema.safeParse(body({})).success).toBe(
|
|
30
|
+
false,
|
|
31
|
+
);
|
|
32
|
+
expect(
|
|
33
|
+
RateLimitedErrorResponseSchema.safeParse(body({ retryAfterSeconds: -1 }))
|
|
34
|
+
.success,
|
|
35
|
+
).toBe(false);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("refuses any other code", () => {
|
|
39
|
+
expect(
|
|
40
|
+
RateLimitedErrorResponseSchema.safeParse(
|
|
41
|
+
body({ error: "FORBIDDEN", retryAfterSeconds: 3 }),
|
|
42
|
+
).success,
|
|
43
|
+
).toBe(false);
|
|
44
|
+
expect(RATE_LIMITED_ERROR_CODE).toBe("RATE_LIMIT_EXCEEDED");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("is reachable from the package root", () => {
|
|
48
|
+
expect(root.RateLimitedErrorResponseSchema).toBe(
|
|
49
|
+
RateLimitedErrorResponseSchema,
|
|
50
|
+
);
|
|
51
|
+
expect(root.RATE_LIMITED_ERROR_CODE).toBe(RATE_LIMITED_ERROR_CODE);
|
|
52
|
+
});
|
|
53
|
+
});
|
package/src/rate-limit/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Rate limiting vocabulary types.
|
|
3
5
|
* @see PRD-00012 for foundational implementation
|
|
@@ -21,3 +23,34 @@ export interface RateLimitResult {
|
|
|
21
23
|
remaining: number;
|
|
22
24
|
resetAt: number;
|
|
23
25
|
}
|
|
26
|
+
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// The rate-limited error envelope (owner ruling 2026-10-06: retry prose is
|
|
29
|
+
// FACTS ONLY; control ADR affordance-system)
|
|
30
|
+
// =============================================================================
|
|
31
|
+
|
|
32
|
+
/** The error code every rate-limited response carries. */
|
|
33
|
+
export const RATE_LIMITED_ERROR_CODE = "RATE_LIMIT_EXCEEDED" as const;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A 429 body, exactly as backend's shared limiter sends it
|
|
37
|
+
* (`{ error: 'RATE_LIMIT_EXCEEDED', scope?, message }`), plus the one fact a
|
|
38
|
+
* client needs to say when the window resets.
|
|
39
|
+
*
|
|
40
|
+
* `retryAfterSeconds` mirrors the `Retry-After` header: whole seconds until the
|
|
41
|
+
* window resets, or null when the limiter cannot say. It is a FACT, so the
|
|
42
|
+
* message states it ("Too many requests. Available in 30s.") and never
|
|
43
|
+
* tells the reader to retry; a retry control, if a surface has one, is that
|
|
44
|
+
* surface's own control label.
|
|
45
|
+
*/
|
|
46
|
+
export const RateLimitedErrorResponseSchema = z
|
|
47
|
+
.object({
|
|
48
|
+
error: z.literal(RATE_LIMITED_ERROR_CODE),
|
|
49
|
+
scope: z.enum(["email", "ip", "global"]).optional(),
|
|
50
|
+
message: z.string(),
|
|
51
|
+
retryAfterSeconds: z.number().int().nonnegative().nullable(),
|
|
52
|
+
})
|
|
53
|
+
.strict();
|
|
54
|
+
export type RateLimitedErrorResponse = z.infer<
|
|
55
|
+
typeof RateLimitedErrorResponseSchema
|
|
56
|
+
>;
|
|
@@ -157,6 +157,9 @@ export type ResourceKey =
|
|
|
157
157
|
// `useResource` disables a query whose `toQueryKey` throws, the panel it backs
|
|
158
158
|
// never fetched at all. An unregistered key is not a stale read, it is no read.
|
|
159
159
|
| { type: "factoryKpis"; scope: "system" }
|
|
160
|
+
// Change lineage over the release ledger (ADR-CONTRACTS-222, backend
|
|
161
|
+
// ADR-BE-926): each release with its commits, PRDs, workers, run and health.
|
|
162
|
+
| { type: "factoryLineage"; scope: "system" }
|
|
160
163
|
// Everything awaiting the viewer's decision, across every domain
|
|
161
164
|
// (ADR-CONT-104). ORG-scoped, not user-scoped, even though the content is
|
|
162
165
|
// per-viewer: the bucket differs per org, so a user-keyed entry would serve
|
package/src/resource-keys.ts
CHANGED
|
@@ -97,6 +97,10 @@ export type {
|
|
|
97
97
|
WorkflowOutcomeData,
|
|
98
98
|
WorkflowOutcomePart,
|
|
99
99
|
WorkflowOutcomeDataPart,
|
|
100
|
+
// Affordance offer types (non-governed, the frozen offer on a pushed chat, control ADR affordance-system)
|
|
101
|
+
AffordanceOfferData,
|
|
102
|
+
AffordanceOfferPart,
|
|
103
|
+
AffordanceOfferDataPart,
|
|
100
104
|
// Execution result types (Phase 5)
|
|
101
105
|
ExecutionArtifactStatus,
|
|
102
106
|
ExecutionResultSummary,
|
|
@@ -213,5 +217,13 @@ export type {
|
|
|
213
217
|
|
|
214
218
|
// Rate limit domain types
|
|
215
219
|
// @see PRD-00013 for contracts integration
|
|
216
|
-
export type {
|
|
217
|
-
|
|
220
|
+
export type {
|
|
221
|
+
RateLimitConfig,
|
|
222
|
+
RateLimitResult,
|
|
223
|
+
RateLimitedErrorResponse,
|
|
224
|
+
} from "../rate-limit/index";
|
|
225
|
+
export {
|
|
226
|
+
RATE_LIMITED_ERROR_CODE,
|
|
227
|
+
RateLimitTier,
|
|
228
|
+
RateLimitedErrorResponseSchema,
|
|
229
|
+
} from "../rate-limit/index";
|
|
@@ -299,13 +299,24 @@ export {
|
|
|
299
299
|
AFFORDANCE_UNAVAILABLE_REASONS,
|
|
300
300
|
AffordanceAvailabilityIdSchema,
|
|
301
301
|
AffordanceAvailabilitySchema,
|
|
302
|
+
AffordanceCoverageSchema,
|
|
302
303
|
AffordanceIdSchema,
|
|
303
304
|
AffordanceSchema,
|
|
305
|
+
AvailableAffordanceSchema,
|
|
306
|
+
AvailableAffordancesSchema,
|
|
307
|
+
ChatOpenArgsSchema,
|
|
308
|
+
CompanyMdDocArgsSchema,
|
|
309
|
+
ExecutionOpenArgsSchema,
|
|
304
310
|
MAX_OFFERED_AFFORDANCES,
|
|
311
|
+
NO_AFFORDANCE_REASONS,
|
|
305
312
|
NO_ARG_AFFORDANCE_IDS,
|
|
313
|
+
NoAffordanceReasonSchema,
|
|
306
314
|
OfferedAffordanceSchema,
|
|
315
|
+
OrgStructureOpenReviewArgsSchema,
|
|
307
316
|
PROJECTED_AFFORDANCE_IDS,
|
|
308
317
|
ReviewOpenArgsSchema,
|
|
318
|
+
SourceSyncOpenUpdateArgsSchema,
|
|
319
|
+
TeamOpenArgsSchema,
|
|
309
320
|
sameAffordances,
|
|
310
321
|
} from "../affordances/index";
|
|
311
322
|
|
|
@@ -315,8 +326,12 @@ export type {
|
|
|
315
326
|
AffordanceAvailability,
|
|
316
327
|
AffordanceAvailabilityId,
|
|
317
328
|
AffordanceBindingKind,
|
|
329
|
+
AffordanceCoverage,
|
|
318
330
|
AffordanceId,
|
|
319
331
|
AffordanceUnavailableReason,
|
|
332
|
+
AvailableAffordance,
|
|
333
|
+
AvailableAffordances,
|
|
334
|
+
NoAffordanceReason,
|
|
320
335
|
OfferedAffordance,
|
|
321
336
|
ProjectedAffordanceId,
|
|
322
337
|
} from "../affordances/index";
|