@sealkeeper/schema 0.4.5 → 0.4.7
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/README.md +2 -2
- package/dist/api.d.ts +30 -38
- package/dist/api.js +87 -42
- package/dist/client-address.d.ts +6 -0
- package/dist/client-address.js +81 -0
- package/dist/credential.d.ts +1 -66
- package/dist/credential.js +25 -63
- package/dist/events.d.ts +1 -0
- package/dist/events.js +13 -1
- package/dist/goal.js +2 -2
- package/dist/hidden.d.ts +1 -0
- package/dist/hidden.js +5 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/json-shape.d.ts +9 -0
- package/dist/json-shape.js +70 -0
- package/dist/moderation.d.ts +2 -1
- package/dist/moderation.js +169 -75
- package/dist/seal-conformance.js +2 -2
- package/dist/seal-verify.d.ts +21 -0
- package/dist/seal-verify.js +63 -0
- package/dist/standing.js +1 -1
- package/dist/tasks.d.ts +2 -0
- package/dist/tasks.js +14 -4
- package/package.json +2 -6
- package/dist/db/agent-milestones.d.ts +0 -75
- package/dist/db/agent-milestones.js +0 -16
- package/dist/db/agent-renames.d.ts +0 -126
- package/dist/db/agent-renames.js +0 -20
- package/dist/db/agents.d.ts +0 -266
- package/dist/db/agents.js +0 -79
- package/dist/db/client.d.ts +0 -2471
- package/dist/db/client.js +0 -40
- package/dist/db/credentials.d.ts +0 -143
- package/dist/db/credentials.js +0 -16
- package/dist/db/deleted-operators.d.ts +0 -75
- package/dist/db/deleted-operators.js +0 -13
- package/dist/db/events.d.ts +0 -160
- package/dist/db/events.js +0 -41
- package/dist/db/feed-items.d.ts +0 -109
- package/dist/db/feed-items.js +0 -21
- package/dist/db/index.d.ts +0 -76
- package/dist/db/index.js +0 -28
- package/dist/db/migrate.d.ts +0 -1
- package/dist/db/migrate.js +0 -34
- package/dist/db/migrator.d.ts +0 -4
- package/dist/db/migrator.js +0 -26
- package/dist/db/operator-identities.d.ts +0 -211
- package/dist/db/operator-identities.js +0 -49
- package/dist/db/operator-level-grants.d.ts +0 -109
- package/dist/db/operator-level-grants.js +0 -30
- package/dist/db/operator-slugs.d.ts +0 -92
- package/dist/db/operator-slugs.js +0 -25
- package/dist/db/operators.d.ts +0 -228
- package/dist/db/operators.js +0 -39
- package/dist/db/quota-counters.d.ts +0 -109
- package/dist/db/quota-counters.js +0 -17
- package/dist/db/ratings.d.ts +0 -160
- package/dist/db/ratings.js +0 -27
- package/dist/db/scores.d.ts +0 -160
- package/dist/db/scores.js +0 -15
- package/dist/db/standing.d.ts +0 -264
- package/dist/db/standing.js +0 -34
- package/dist/db/task-claim-failures.d.ts +0 -143
- package/dist/db/task-claim-failures.js +0 -37
- package/dist/db/task-outcomes.d.ts +0 -145
- package/dist/db/task-outcomes.js +0 -25
- package/dist/db/tasks.d.ts +0 -381
- package/dist/db/tasks.js +0 -100
- package/dist/db/timestamps.d.ts +0 -4
- package/dist/db/timestamps.js +0 -24
- package/dist/db/url.d.ts +0 -12
- package/dist/db/url.js +0 -25
package/dist/credential.js
CHANGED
|
@@ -2,7 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { AgentId, Ed25519PublicKey } from './agent-id.js';
|
|
3
3
|
import { Dimension } from './dimensions.js';
|
|
4
4
|
import { Jws } from './envelope.js';
|
|
5
|
-
import {
|
|
5
|
+
import { StoredVersion } from './events.js';
|
|
6
6
|
import { CountedCounts, Level, StandingCounts } from './standing.js';
|
|
7
7
|
// The issuer every SEAL carries as iss from the SealKeeper cutover on.
|
|
8
8
|
export const CREDENTIAL_ISSUER = 'sealkeeper.run';
|
|
@@ -29,7 +29,6 @@ export function acceptedIssuer(iss, nowSeconds) {
|
|
|
29
29
|
export const WELL_KNOWN_PATH = '/.well-known/seal.json';
|
|
30
30
|
export const LEGACY_WELL_KNOWN_PATH = '/.well-known/vouched.json';
|
|
31
31
|
export const WELL_KNOWN_URL = `https://${CREDENTIAL_ISSUER}${WELL_KNOWN_PATH}`;
|
|
32
|
-
export const LEGACY_WELL_KNOWN_URL = `https://vouched.run${LEGACY_WELL_KNOWN_PATH}`;
|
|
33
32
|
// The card extension a SEAL travels under. The two old URIs are kept beside
|
|
34
33
|
// it for one release, VOU-77 drops them.
|
|
35
34
|
export const SEAL_EXTENSION_URI = 'https://sealkeeper.run/ext/seal/v1';
|
|
@@ -56,12 +55,6 @@ export const SEAL_VERSION = 1;
|
|
|
56
55
|
// writing version 1 until they are gone, and verifiers from this release
|
|
57
56
|
// on accept both. SEAL standard section 9.
|
|
58
57
|
export const SEAL_VERSIONS = [1, 2];
|
|
59
|
-
// SEALs issued before version 1 carry no ver. Verifiers accept them as
|
|
60
|
-
// legacy until the end of 25 September 2026 UTC, which is past the 24 hour
|
|
61
|
-
// life of any SEAL issued before the deploy. From then on a SEAL without
|
|
62
|
-
// ver is broken, unsupported_version. Unix seconds, the first second no
|
|
63
|
-
// longer accepted.
|
|
64
|
-
export const LEGACY_UNTIL = Date.UTC(2026, 8, 26) / 1000;
|
|
65
58
|
// One identity attestation reference, SEAL standard section 4a. A pointer
|
|
66
59
|
// to an attestation an external provider made, never the attestation, a
|
|
67
60
|
// name or a tenant id. kind is one of the four names or a URL for anything
|
|
@@ -118,8 +111,8 @@ const v1Payload = (iss) => z
|
|
|
118
111
|
ver: z.literal(SEAL_VERSION),
|
|
119
112
|
iat: Seconds,
|
|
120
113
|
exp: Seconds,
|
|
121
|
-
agent_version:
|
|
122
|
-
version:
|
|
114
|
+
agent_version: StoredVersion,
|
|
115
|
+
version: StoredVersion,
|
|
123
116
|
level: Level,
|
|
124
117
|
scores: Scores,
|
|
125
118
|
counts: StandingCounts,
|
|
@@ -143,8 +136,8 @@ const v2Payload = (iss) => z
|
|
|
143
136
|
ver: z.literal(2),
|
|
144
137
|
iat: Seconds,
|
|
145
138
|
exp: Seconds,
|
|
146
|
-
agent_version:
|
|
147
|
-
version:
|
|
139
|
+
agent_version: StoredVersion,
|
|
140
|
+
version: StoredVersion,
|
|
148
141
|
level: Level,
|
|
149
142
|
scores: Scores,
|
|
150
143
|
counts: StandingCounts,
|
|
@@ -160,65 +153,38 @@ const v2Payload = (iss) => z
|
|
|
160
153
|
.refine((c) => c.counted.seed_tasks <= c.counts.seed_tasks &&
|
|
161
154
|
c.counted.server_checked_tasks <= c.counts.server_checked_tasks &&
|
|
162
155
|
c.counted.confirmed_tasks <= c.counts.confirmed_tasks, 'counted must not exceed counts');
|
|
163
|
-
// The payload issued before version 1, with no ver. Accepted by verifiers
|
|
164
|
-
// until LEGACY_UNTIL, never issued again. seed_tasks is optional because a
|
|
165
|
-
// SEAL issued before it was added has none.
|
|
166
|
-
const legacyPayload = (iss) => z
|
|
167
|
-
.strictObject({
|
|
168
|
-
iss,
|
|
169
|
-
sub: AgentId,
|
|
170
|
-
iat: Seconds,
|
|
171
|
-
exp: Seconds,
|
|
172
|
-
version: Version,
|
|
173
|
-
scores: Scores,
|
|
174
|
-
counts: z.strictObject({
|
|
175
|
-
events: Count,
|
|
176
|
-
verified_tasks: Count,
|
|
177
|
-
seed_tasks: Count.optional(),
|
|
178
|
-
}),
|
|
179
|
-
})
|
|
180
|
-
.refine((c) => c.exp > c.iat, 'exp must be after iat')
|
|
181
|
-
.refine(withinMaxTtl, MAX_TTL_MESSAGE);
|
|
182
156
|
// The issuer side. iss is CREDENTIAL_ISSUER only.
|
|
183
157
|
export const CredentialPayload = v1Payload(IssuedIssuer);
|
|
184
158
|
export const CredentialPayloadV2 = v2Payload(IssuedIssuer);
|
|
185
|
-
export const LegacyCredentialPayload = legacyPayload(IssuedIssuer);
|
|
186
159
|
// The verifier side. iss may also be a LEGACY_ISSUERS entry. The shape has
|
|
187
160
|
// no clock, so read these through parseSealPayload, never on their own.
|
|
188
161
|
export const VerifiedCredentialPayload = v1Payload(VerifiedIssuer);
|
|
189
162
|
export const VerifiedCredentialPayloadV2 = v2Payload(VerifiedIssuer);
|
|
190
|
-
|
|
191
|
-
//
|
|
192
|
-
//
|
|
163
|
+
// Any payload a verifier accepts today, version 1 or version 2, from the
|
|
164
|
+
// current issuer or a legacy one. Version 2 has every version 1 field with
|
|
165
|
+
// the same meaning, so a reader of version 1 fields takes both.
|
|
193
166
|
export const SealPayload = z.union([
|
|
194
167
|
VerifiedCredentialPayload,
|
|
195
168
|
VerifiedCredentialPayloadV2,
|
|
196
|
-
VerifiedLegacyCredentialPayload,
|
|
197
169
|
]);
|
|
198
|
-
// A versioned payload carries every legacy field too, so the guard is on
|
|
199
|
-
// ver, the narrower of the two. Its false branch is the legacy shape. The
|
|
200
|
-
// name is kept from when version 1 was the only one.
|
|
201
|
-
export const isSealV1 = (p) => 'ver' in p;
|
|
202
170
|
// The counted evidence a SEAL carries, version 2 on, null before.
|
|
203
171
|
export const sealCounted = (p) => 'counted' in p ? p.counted : null;
|
|
204
172
|
const hasVer = (raw) => typeof raw === 'object' && raw !== null && 'ver' in raw;
|
|
205
173
|
/*
|
|
206
174
|
* Whether a verifier understands the version of a signed payload. Read
|
|
207
175
|
* after the signature and the issuer check out and before the shape. ver 1
|
|
208
|
-
* and 2 (SEAL_VERSIONS) are understood. Any other ver is
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
176
|
+
* and 2 (SEAL_VERSIONS) are understood. Any other ver is
|
|
177
|
+
* unsupported_version, as section 9 of the standard says, never valid with
|
|
178
|
+
* an unknown meaning. So is no ver at all, a SEAL issued before version 1,
|
|
179
|
+
* whose last one expired on 26 September 2026. Anything that is not an
|
|
180
|
+
* object is left to the shape check.
|
|
212
181
|
*/
|
|
213
|
-
export function sealVersionProblem(raw
|
|
182
|
+
export function sealVersionProblem(raw) {
|
|
214
183
|
if (typeof raw !== 'object' || raw === null)
|
|
215
184
|
return null;
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
: 'unsupported_version';
|
|
220
|
-
}
|
|
221
|
-
return nowSeconds < LEGACY_UNTIL ? null : 'unsupported_version';
|
|
185
|
+
return hasVer(raw) && SEAL_VERSIONS.includes(raw.ver)
|
|
186
|
+
? null
|
|
187
|
+
: 'unsupported_version';
|
|
222
188
|
}
|
|
223
189
|
/*
|
|
224
190
|
* The iat half of step 4 of the standard, section 3. "Check exp is in the
|
|
@@ -232,9 +198,8 @@ export function sealIatProblem(iat, nowSeconds) {
|
|
|
232
198
|
return iat - nowSeconds > SEAL_CLOCK_SKEW_SECONDS ? 'not_yet_valid' : null;
|
|
233
199
|
}
|
|
234
200
|
// The issuer, then the version check above, then the shape for that
|
|
235
|
-
// version, in the standard's order.
|
|
236
|
-
//
|
|
237
|
-
// acceptedIssuer and sealVersionProblem itself.
|
|
201
|
+
// version, in the standard's order. verifySeal reads a verified payload
|
|
202
|
+
// through this.
|
|
238
203
|
export function parseSealPayload(raw, nowSeconds) {
|
|
239
204
|
const iss = typeof raw === 'object' && raw !== null && 'iss' in raw
|
|
240
205
|
? raw.iss
|
|
@@ -242,14 +207,12 @@ export function parseSealPayload(raw, nowSeconds) {
|
|
|
242
207
|
if (!acceptedIssuer(iss, nowSeconds)) {
|
|
243
208
|
return { ok: false, reason: 'wrong_issuer' };
|
|
244
209
|
}
|
|
245
|
-
const problem = sealVersionProblem(raw
|
|
210
|
+
const problem = sealVersionProblem(raw);
|
|
246
211
|
if (problem)
|
|
247
212
|
return { ok: false, reason: problem };
|
|
248
|
-
const parsed = (
|
|
249
|
-
?
|
|
250
|
-
: raw
|
|
251
|
-
? VerifiedCredentialPayloadV2
|
|
252
|
-
: VerifiedCredentialPayload).safeParse(raw);
|
|
213
|
+
const parsed = (hasVer(raw) && raw.ver === 2
|
|
214
|
+
? VerifiedCredentialPayloadV2
|
|
215
|
+
: VerifiedCredentialPayload).safeParse(raw);
|
|
253
216
|
return parsed.success
|
|
254
217
|
? { ok: true, payload: parsed.data }
|
|
255
218
|
: { ok: false, reason: 'malformed' };
|
|
@@ -314,9 +277,8 @@ export const AgentSkill = z.strictObject({
|
|
|
314
277
|
examples: z.array(z.string().min(1).max(1024)).max(32).optional(),
|
|
315
278
|
});
|
|
316
279
|
const Modes = z.array(z.string().min(1).max(128)).max(32).default(['text']);
|
|
317
|
-
// The subset of the A2A agent card that
|
|
318
|
-
// never writes a field it did not mean to.
|
|
319
|
-
// the loose AgentCardResponse instead.
|
|
280
|
+
// The subset of the A2A agent card that SealKeeper emits, strict so the
|
|
281
|
+
// CLI never writes a field it did not mean to.
|
|
320
282
|
export const AgentCard = z.strictObject({
|
|
321
283
|
protocolVersion: z.literal(A2A_PROTOCOL_VERSION),
|
|
322
284
|
name: z.string().min(1).max(128),
|
package/dist/events.d.ts
CHANGED
package/dist/events.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { TaskType } from './dimensions.js';
|
|
3
|
+
import { HIDDEN } from './hidden.js';
|
|
3
4
|
import { Sha256Hex, TaskOutcome } from './tasks.js';
|
|
4
5
|
/*
|
|
5
6
|
* The Zod pattern, shown once. Every schema file in this package follows it.
|
|
@@ -25,7 +26,18 @@ import { Sha256Hex, TaskOutcome } from './tasks.js';
|
|
|
25
26
|
*
|
|
26
27
|
* Use parse to throw on bad input and safeParse to get { success, data, error }.
|
|
27
28
|
*/
|
|
28
|
-
|
|
29
|
+
/*
|
|
30
|
+
* An agent version as it is stored and read back. Only the length rule,
|
|
31
|
+
* since a row written before Version had a character rule may hold
|
|
32
|
+
* anything. Every answer and every read of a stored row uses this, so an
|
|
33
|
+
* old stored version never throws. New input is parsed with Version.
|
|
34
|
+
*/
|
|
35
|
+
export const StoredVersion = z.string().min(1).max(32);
|
|
36
|
+
// An agent version as a caller sends it, in an event, a registration or a
|
|
37
|
+
// version change. It is signed into the SEAL and shown on public pages, so
|
|
38
|
+
// it refuses the characters OperatorDisplayName refuses (HIDDEN) and a
|
|
39
|
+
// space at either end, on top of the length rule.
|
|
40
|
+
export const Version = StoredVersion.refine((v) => !HIDDEN.test(v), 'No control characters').refine((v) => v === v.trim(), 'No space at the start or end');
|
|
29
41
|
const Name = z
|
|
30
42
|
.string()
|
|
31
43
|
.min(1)
|
package/dist/goal.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { AgentId } from './agent-id.js';
|
|
3
|
-
import {
|
|
3
|
+
import { StoredVersion } from './events.js';
|
|
4
4
|
import { LADDER, Level } from './standing.js';
|
|
5
5
|
// GET /v1/agents/:id/goal. What the agent's current version needs for its
|
|
6
6
|
// next level, threshold by threshold, and what to do next. The API sends
|
|
@@ -158,7 +158,7 @@ export const GoalPending = z.strictObject({
|
|
|
158
158
|
});
|
|
159
159
|
export const GoalResponse = z.strictObject({
|
|
160
160
|
agentId: AgentId,
|
|
161
|
-
version:
|
|
161
|
+
version: StoredVersion,
|
|
162
162
|
level: Level,
|
|
163
163
|
nextLevel: Level.nullable(),
|
|
164
164
|
ladder: z.array(GoalLadderStep),
|
package/dist/hidden.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const HIDDEN: RegExp;
|
package/dist/hidden.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Control, format, private use, unassigned and lone surrogate characters
|
|
2
|
+
// (bidi overrides, zero width joiners and the like), and the line and
|
|
3
|
+
// paragraph separators, which can hide, reorder or break what a reader sees.
|
|
4
|
+
// Shared by the text rules in this package and not exported from it.
|
|
5
|
+
export const HIDDEN = /[\p{C}\p{Zl}\p{Zp}]/u;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,16 +3,18 @@ export * from './agent-name.js';
|
|
|
3
3
|
export * from './api.js';
|
|
4
4
|
export * from './badge.js';
|
|
5
5
|
export * from './base64url.js';
|
|
6
|
+
export * from './client-address.js';
|
|
6
7
|
export * from './credential.js';
|
|
7
8
|
export * from './dimensions.js';
|
|
8
9
|
export * from './envelope.js';
|
|
9
10
|
export * from './events.js';
|
|
10
11
|
export * from './goal.js';
|
|
12
|
+
export * from './json-shape.js';
|
|
11
13
|
export * from './moderation.js';
|
|
12
14
|
export * from './operator-domains.js';
|
|
13
15
|
export * from './policy.js';
|
|
14
16
|
export * from './runtime.js';
|
|
17
|
+
export * from './seal-verify.js';
|
|
15
18
|
export * from './standing.js';
|
|
16
19
|
export * from './tasks.js';
|
|
17
20
|
export * from './top-dimensions.js';
|
|
18
|
-
export declare const SCHEMA_VERSION = 1;
|
package/dist/index.js
CHANGED
|
@@ -3,16 +3,18 @@ export * from './agent-name.js';
|
|
|
3
3
|
export * from './api.js';
|
|
4
4
|
export * from './badge.js';
|
|
5
5
|
export * from './base64url.js';
|
|
6
|
+
export * from './client-address.js';
|
|
6
7
|
export * from './credential.js';
|
|
7
8
|
export * from './dimensions.js';
|
|
8
9
|
export * from './envelope.js';
|
|
9
10
|
export * from './events.js';
|
|
10
11
|
export * from './goal.js';
|
|
12
|
+
export * from './json-shape.js';
|
|
11
13
|
export * from './moderation.js';
|
|
12
14
|
export * from './operator-domains.js';
|
|
13
15
|
export * from './policy.js';
|
|
14
16
|
export * from './runtime.js';
|
|
17
|
+
export * from './seal-verify.js';
|
|
15
18
|
export * from './standing.js';
|
|
16
19
|
export * from './tasks.js';
|
|
17
20
|
export * from './top-dimensions.js';
|
|
18
|
-
export const SCHEMA_VERSION = 1;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export type JsonShapeLimits = {
|
|
3
|
+
readonly maxDepth: number;
|
|
4
|
+
readonly maxKeys: number;
|
|
5
|
+
readonly maxBytes: number;
|
|
6
|
+
};
|
|
7
|
+
export type JsonShapeIssue = 'too_deep' | 'too_many_keys';
|
|
8
|
+
export declare function jsonShapeIssue(value: unknown, limits: Pick<JsonShapeLimits, 'maxDepth' | 'maxKeys'>): JsonShapeIssue | null;
|
|
9
|
+
export declare function boundedJsonObject(name: string, limits: JsonShapeLimits): z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { utf8Encode } from './base64url.js';
|
|
3
|
+
/*
|
|
4
|
+
* The first depth or key count limit a JSON value breaks, or null when it
|
|
5
|
+
* keeps to both.
|
|
6
|
+
*
|
|
7
|
+
* Walks with its own stack rather than recursing, so a value nested
|
|
8
|
+
* thousands deep cannot overflow the call stack, and stops at the first
|
|
9
|
+
* breach. Run it before JSON.stringify on anything a caller sent.
|
|
10
|
+
* stringify recurses and throws RangeError past about 7,700 levels, and
|
|
11
|
+
* indented output grows with the square of the depth (VOU-214).
|
|
12
|
+
*/
|
|
13
|
+
export function jsonShapeIssue(value, limits) {
|
|
14
|
+
const stack = [];
|
|
15
|
+
const push = (v, depth) => {
|
|
16
|
+
if (typeof v === 'object' && v !== null)
|
|
17
|
+
stack.push({ node: v, depth });
|
|
18
|
+
};
|
|
19
|
+
push(value, 1);
|
|
20
|
+
let keys = 0;
|
|
21
|
+
for (let top = stack.pop(); top !== undefined; top = stack.pop()) {
|
|
22
|
+
if (top.depth > limits.maxDepth)
|
|
23
|
+
return 'too_deep';
|
|
24
|
+
let children;
|
|
25
|
+
if (Array.isArray(top.node)) {
|
|
26
|
+
children = top.node;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
children = Object.values(top.node);
|
|
30
|
+
keys += children.length;
|
|
31
|
+
if (keys > limits.maxKeys)
|
|
32
|
+
return 'too_many_keys';
|
|
33
|
+
}
|
|
34
|
+
for (const child of children)
|
|
35
|
+
push(child, top.depth + 1);
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
/*
|
|
40
|
+
* A JSON object held to the limits. The depth and key checks run first, so
|
|
41
|
+
* the byte check only ever stringifies a value that cannot throw, and a
|
|
42
|
+
* breach is a Zod issue (a 400 at the API), never a RangeError (a 500).
|
|
43
|
+
* superRefine is used rather than refine so each breach gets its own
|
|
44
|
+
* message and the byte check can be skipped once one is found.
|
|
45
|
+
*/
|
|
46
|
+
export function boundedJsonObject(name, limits) {
|
|
47
|
+
return z.record(z.string(), z.unknown()).superRefine((value, ctx) => {
|
|
48
|
+
const issue = jsonShapeIssue(value, limits);
|
|
49
|
+
if (issue === 'too_deep') {
|
|
50
|
+
ctx.addIssue({
|
|
51
|
+
code: 'custom',
|
|
52
|
+
message: `${name} must nest at most ${limits.maxDepth} levels deep`,
|
|
53
|
+
});
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (issue === 'too_many_keys') {
|
|
57
|
+
ctx.addIssue({
|
|
58
|
+
code: 'custom',
|
|
59
|
+
message: `${name} must have at most ${limits.maxKeys} keys`,
|
|
60
|
+
});
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (utf8Encode(JSON.stringify(value)).length > limits.maxBytes) {
|
|
64
|
+
ctx.addIssue({
|
|
65
|
+
code: 'custom',
|
|
66
|
+
message: `${name} must be at most ${limits.maxBytes} bytes`,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
package/dist/moderation.d.ts
CHANGED
|
@@ -15,12 +15,13 @@ export declare const PROTECTED_PREFIXES: readonly string[];
|
|
|
15
15
|
export declare function protectedNameOf(text: string): string | null;
|
|
16
16
|
export declare const RESERVED_WORDS: readonly string[];
|
|
17
17
|
export declare function isReservedWord(text: string): boolean;
|
|
18
|
-
export type NameRefusalCode = 'name_protected' | 'name_reserved';
|
|
18
|
+
export type NameRefusalCode = 'name_protected' | 'name_reserved' | 'name_mixed_script';
|
|
19
19
|
export type NameRefusal = {
|
|
20
20
|
code: NameRefusalCode;
|
|
21
21
|
message: string;
|
|
22
22
|
};
|
|
23
23
|
export declare function moderateSlug(slug: string): NameRefusal | null;
|
|
24
|
+
export declare function mixedScriptOf(text: string): string | null;
|
|
24
25
|
export declare function moderateDisplayName(name: string): NameRefusal | null;
|
|
25
26
|
export declare function slugBase(login: string): string;
|
|
26
27
|
export declare const suffixedSlug: (base: string, n: number) => string;
|