@sema-agent/settings-schema 11.2.0 → 12.0.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 +112 -0
- package/README.md +2 -1
- package/conformance/VERSION +1 -1
- package/conformance/cases/c40-s712-identity-only-what-reads-out/expected.json +6 -3
- package/conformance/cases/c41-s792-encoded-pem-identity/expected.json +4 -2
- package/conformance/cases/c45-s792-identity-bounds-and-decode-depth/expected.json +4 -2
- package/conformance/cases/c46-s811-host-name-url-userinfo-withheld/expected.json +2 -1
- package/conformance/cases/c73-projects-extended-registration-reads/expected.json +150 -0
- package/conformance/cases/c73-projects-extended-registration-reads/input.json +42 -0
- package/conformance/cases/c73-projects-extended-registration-reads/meta.json +6 -0
- package/conformance/cases/c74-projects-over-bound-refused/expected.json +89 -0
- package/conformance/cases/c74-projects-over-bound-refused/input.json +29 -0
- package/conformance/cases/c74-projects-over-bound-refused/meta.json +5 -0
- package/conformance/cases/c75-projects-patch-remote-uniqueness/expected.json +89 -0
- package/conformance/cases/c75-projects-patch-remote-uniqueness/input.json +35 -0
- package/conformance/cases/c75-projects-patch-remote-uniqueness/meta.json +5 -0
- package/conformance/cases/cli01-model-name-nfc-vs-nfd/expected.json +4 -2
- package/conformance/cases/cli02-control-and-zero-width-chars/expected.json +4 -2
- package/dist/api/feedback.js +2 -3
- package/dist/api/scopes.js +2 -1
- package/dist/atomic-write.d.ts +6 -0
- package/dist/atomic-write.js +23 -6
- package/dist/cli.d.ts +8 -4
- package/dist/cli.js +55 -10
- package/dist/config-d-file.d.ts +12 -2
- package/dist/config-d-file.js +36 -9
- package/dist/config-dir-io.js +4 -3
- package/dist/config-dir-migration.d.ts +5 -3
- package/dist/config-dir-migration.js +19 -9
- package/dist/config-fns.d.ts +14 -2
- package/dist/config-fns.js +13 -1
- package/dist/cross-domain.d.ts +8 -3
- package/dist/cross-domain.js +23 -13
- package/dist/file-edit.js +7 -5
- package/dist/file-store.js +2 -1
- package/dist/fleet.js +3 -4
- package/dist/hooks.d.ts +14 -1
- package/dist/hooks.js +61 -16
- package/dist/host-path.d.ts +17 -0
- package/dist/host-path.js +22 -0
- package/dist/integer.js +2 -1
- package/dist/local-load.d.ts +1 -1
- package/dist/local-load.js +9 -31
- package/dist/migration-receipt.d.ts +4 -3
- package/dist/migration-receipt.js +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/one-time-migrations.d.ts +6 -4
- package/dist/one-time-migrations.js +73 -6
- package/dist/quoted-issue.d.ts +41 -0
- package/dist/quoted-issue.js +35 -0
- package/dist/remote-exec.d.ts +3 -0
- package/dist/remote-exec.js +12 -7
- package/dist/resolve-roster.d.ts +1 -1
- package/dist/resolve-roster.js +3 -3
- package/dist/retired-role-words.d.ts +5 -0
- package/dist/retired-role-words.js +25 -0
- package/dist/rfc3339.d.ts +10 -0
- package/dist/rfc3339.js +12 -0
- package/dist/safety-merge-spec.d.ts +2 -2
- package/dist/types.d.ts +140 -32
- package/dist/types.js +215 -114
- package/dist/web-admin-credential.d.ts +2 -2
- package/dist/web-admin-credential.js +5 -10
- package/dist/write-failure.d.ts +16 -0
- package/dist/write-failure.js +43 -0
- package/package.json +1 -1
|
@@ -22,16 +22,11 @@
|
|
|
22
22
|
import { z } from "zod";
|
|
23
23
|
import { looksLikeJwt } from "./api/auth-bridge.js";
|
|
24
24
|
import { NON_SECRET_URL_NO_MIGRATION } from "./types.js";
|
|
25
|
+
import { buildQuotedIssue } from "./quoted-issue.js";
|
|
26
|
+
import { RFC3339_DATE_TIME } from "./rfc3339.js"; // the package's one RFC 3339 date-time judge (a project registration's `archivedAt` reads the same one)
|
|
25
27
|
import { WEB_ADMIN_ENV } from "./web-admin-env.js";
|
|
26
28
|
/** 信封 `kind` 的闭集今只有一员(`SEALED_BOX_ALG` 同式的字面常量:schema 的字面与读方的比较都引它)。 */
|
|
27
29
|
export const WEB_ADMIN_CREDENTIAL_ENVELOPE_KIND = "user-session";
|
|
28
|
-
/** RFC 3339 `date-time` 的**剖面**:zod 的 `z.iso.datetime({offset:true})` 管日历有效性(月日范围、闰年、时分秒范围),
|
|
29
|
-
* 这里的正则自己判另三处 —— 秒必备、数字偏移必须是 `±hh:mm`、偏移的时 00–23 / 分 00–59(`10:00Z`、`+0800` 与 `+99:99`
|
|
30
|
-
* 都不是 RFC 3339,后者 `Date.parse` 读成 NaN)。这三处的判据在本正则,不随 zod 哪一版收不收而变。大写 `T` / `Z`、不收闰秒 `:60`:读方普遍用
|
|
31
|
-
* `Date.parse` 取时刻,这是那组形里它处处读得准的子集。 */
|
|
32
|
-
const RFC3339_DATE_TIME = z.iso
|
|
33
|
-
.datetime({ offset: true })
|
|
34
|
-
.regex(/T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/, "must be an RFC 3339 date-time: seconds and a Z / ±hh:mm offset (hh 00-23, mm 00-59) are required");
|
|
35
30
|
/** 一枚**令牌串**的形 —— 裸行 bearer、信封里的 `accessToken` / `refreshToken` 共用这**一条**律:可打印 ASCII
|
|
36
31
|
* (0x20–0x7E),首尾是可见字符(0x21–0x7E)、中间可有空格(共享令牌可以是一句口令 —— 验修轮 N2:今天走得通的
|
|
37
32
|
* 这种令牌不许被本律拒掉)。控制字符、制表、非 ASCII、不可见字符一律不是令牌:判别器把它判 `unreadable`,而不是
|
|
@@ -50,13 +45,13 @@ const TokenString = z.string().regex(TOKEN_CHARS, "must be a token: printable AS
|
|
|
50
45
|
* 文件**取当前值,不用内存旧值(另一个写者可能刚轮换过)。
|
|
51
46
|
* · `expiresAt` —— 访问令牌到期时刻(RFC 3339)。
|
|
52
47
|
* · `issuer` —— 签发它的 web-admin 的**基础 URL**(与读方连 web-admin 的根 URL 同形,可带路径前缀):续签只向同源的 web-admin 发,
|
|
53
|
-
* 同不同源由读方比。URL
|
|
54
|
-
* query / fragment
|
|
48
|
+
* 同不同源由读方比。URL 形判据是包内 URL 判官的「非存量座位」那一只 {@link NON_SECRET_URL_NO_MIGRATION}(http(s)、有 host、userinfo 与
|
|
49
|
+
* query / fragment 里不许夹带凭据;issuer 是 wire 输入、不是存量,一次性迁移不碰它,fragment 拒句因此不指路)—— 本包不另写一份更窄的 URL 律。
|
|
55
50
|
*/
|
|
56
51
|
export const WebAdminCredentialEnvelope = z
|
|
57
52
|
.object({
|
|
58
53
|
kind: z.literal(WEB_ADMIN_CREDENTIAL_ENVELOPE_KIND),
|
|
59
|
-
accessToken: TokenString.refine(looksLikeJwt,
|
|
54
|
+
accessToken: TokenString.refine(looksLikeJwt, buildQuotedIssue `must be a JWT (three dot-separated segments) — a worker pull token never goes into an envelope`),
|
|
60
55
|
refreshToken: TokenString,
|
|
61
56
|
expiresAt: RFC3339_DATE_TIME,
|
|
62
57
|
issuer: NON_SECRET_URL_NO_MIGRATION,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 包内私有(不进主桶、不进 exports 表;零 `node:` 依赖):原子写器(`./atomic-write`)写失败的**唯一一句** —— 按失败落在哪一步、errno 是什么分句,
|
|
3
|
+
* 句尾给那一步对应的出路。写器有两步:在目标所在目录里建临时文件(`create`,连同恢复沿用的模式)、`rename` 盖过目标(`replace`)。
|
|
4
|
+
* 改前一句话包打天下(「cannot write <文件>: <Node 的错误句> … fix the cause」):目录不可写时点名的却是文件(Node 句子里是临时文件的路径),
|
|
5
|
+
* 而可写目录里的只读文件照常写得进 —— 句子把人指向了错的那一个。命令行(`./cli`)认这只错误类型、原样印它的句子。
|
|
6
|
+
*/
|
|
7
|
+
/** 原子写的两步(闭集)。 */
|
|
8
|
+
export type AtomicWriteStep = "create" | "replace";
|
|
9
|
+
/** 一次写失败的句子(纯函数)。认得的 errno 给对应出路;别的 errno(磁盘满、I/O 错 …)给 Node 自己的句子 —— 照样响亮,只是不替它猜出路。 */
|
|
10
|
+
export declare function atomicWriteFailureSentence(step: AtomicWriteStep, dir: string, file: string, cause: unknown): string;
|
|
11
|
+
/** 原子写器抛的错:句子见 {@link atomicWriteFailureSentence};`code` 照抄底层 errno(按 `code` 分支的调用方不受影响),原错误在 `cause`。 */
|
|
12
|
+
export declare class AtomicWriteFailure extends Error {
|
|
13
|
+
readonly step: AtomicWriteStep;
|
|
14
|
+
readonly code: string | undefined;
|
|
15
|
+
constructor(step: AtomicWriteStep, dir: string, file: string, cause: unknown);
|
|
16
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 包内私有(不进主桶、不进 exports 表;零 `node:` 依赖):原子写器(`./atomic-write`)写失败的**唯一一句** —— 按失败落在哪一步、errno 是什么分句,
|
|
3
|
+
* 句尾给那一步对应的出路。写器有两步:在目标所在目录里建临时文件(`create`,连同恢复沿用的模式)、`rename` 盖过目标(`replace`)。
|
|
4
|
+
* 改前一句话包打天下(「cannot write <文件>: <Node 的错误句> … fix the cause」):目录不可写时点名的却是文件(Node 句子里是临时文件的路径),
|
|
5
|
+
* 而可写目录里的只读文件照常写得进 —— 句子把人指向了错的那一个。命令行(`./cli`)认这只错误类型、原样印它的句子。
|
|
6
|
+
*/
|
|
7
|
+
/** `create` 步里「目录本身不让建文件」的 errno:权限不够、只读文件系统、目录不在。出路 = 让目录可写。 */
|
|
8
|
+
const DIRECTORY_NOT_WRITABLE = new Set(["EACCES", "EPERM", "EROFS", "ENOENT"]);
|
|
9
|
+
/** `replace` 步里「目录收新文件、却换不掉这一份」的 errno:不可变标志、粘滞目录里别人的文件。出路 = 让文件可被替换。 */
|
|
10
|
+
const FILE_NOT_REPLACEABLE = new Set(["EACCES", "EPERM"]);
|
|
11
|
+
const errnoOf = (e) => {
|
|
12
|
+
const code = e?.code;
|
|
13
|
+
return typeof code === "string" ? code : undefined;
|
|
14
|
+
};
|
|
15
|
+
const messageOf = (e) => (e instanceof Error ? e.message : String(e)).replace(/\s*\n\s*/g, " ");
|
|
16
|
+
/** 一次写失败的句子(纯函数)。认得的 errno 给对应出路;别的 errno(磁盘满、I/O 错 …)给 Node 自己的句子 —— 照样响亮,只是不替它猜出路。 */
|
|
17
|
+
export function atomicWriteFailureSentence(step, dir, file, cause) {
|
|
18
|
+
const code = errnoOf(cause);
|
|
19
|
+
const tag = code === undefined ? "" : ` (${code})`;
|
|
20
|
+
switch (step) {
|
|
21
|
+
case "create":
|
|
22
|
+
return code !== undefined && DIRECTORY_NOT_WRITABLE.has(code) ? `cannot write into directory ${dir}${tag}: make the directory writable` : `cannot write into directory ${dir}${tag}: ${messageOf(cause)}`;
|
|
23
|
+
case "replace":
|
|
24
|
+
return code !== undefined && FILE_NOT_REPLACEABLE.has(code)
|
|
25
|
+
? `cannot replace ${file}${tag}: make the file replaceable — clear an immutable flag; in a sticky directory only the file's owner may replace it`
|
|
26
|
+
: `cannot replace ${file}${tag}: ${messageOf(cause)}`;
|
|
27
|
+
default: {
|
|
28
|
+
const unhandled = step;
|
|
29
|
+
throw new Error(`atomicWriteFailureSentence: unhandled step ${String(unhandled)}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** 原子写器抛的错:句子见 {@link atomicWriteFailureSentence};`code` 照抄底层 errno(按 `code` 分支的调用方不受影响),原错误在 `cause`。 */
|
|
34
|
+
export class AtomicWriteFailure extends Error {
|
|
35
|
+
step;
|
|
36
|
+
code;
|
|
37
|
+
constructor(step, dir, file, cause) {
|
|
38
|
+
super(atomicWriteFailureSentence(step, dir, file, cause), { cause });
|
|
39
|
+
this.name = "AtomicWriteFailure";
|
|
40
|
+
this.step = step;
|
|
41
|
+
this.code = errnoOf(cause);
|
|
42
|
+
}
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/settings-schema",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0",
|
|
4
4
|
"description": "Sema settings schema — pure config contract (zod domains + effective-config + roster resolution + ref-integrity + remoteExec) shared by sema-web-admin, sema-server, and the TOC desktop/CLI. One source of truth. (Renamed at 1.0.0 from @sema-agent/registry-core — name and docs only, no behavior change; note the range moves 0.19.0 -> 1.0.0, so a dependency must become ^1.0.0. The old names @sema-agent/registry-core <=0.19.0 and @sema-ai/registry-core remain published, frozen, for migration.)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|