@the-40-thieves/obsidian-tc-shared 0.0.1 → 1.0.2
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/LICENSE +201 -0
- package/README.md +2 -4
- package/dist/config.schema.d.ts +1550 -0
- package/dist/config.schema.d.ts.map +1 -0
- package/dist/config.schema.js +208 -0
- package/dist/config.schema.js.map +1 -0
- package/dist/errors.d.ts +49 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +72 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/morgiana.schema.d.ts +180 -0
- package/dist/morgiana.schema.d.ts.map +1 -0
- package/dist/morgiana.schema.js +48 -0
- package/dist/morgiana.schema.js.map +1 -0
- package/dist/net-host.d.ts +16 -0
- package/dist/net-host.d.ts.map +1 -0
- package/dist/net-host.js +39 -0
- package/dist/net-host.js.map +1 -0
- package/dist/result.d.ts +19 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +2 -0
- package/dist/result.js.map +1 -0
- package/dist/schemas/primitives.d.ts +37 -0
- package/dist/schemas/primitives.d.ts.map +1 -0
- package/dist/schemas/primitives.js +36 -0
- package/dist/schemas/primitives.js.map +1 -0
- package/dist/scopes.d.ts +16 -0
- package/dist/scopes.d.ts.map +1 -0
- package/dist/scopes.js +61 -0
- package/dist/scopes.js.map +1 -0
- package/package.json +27 -11
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a host string for binding and loopback comparison: trim, lowercase,
|
|
3
|
+
* and strip a single surrounding pair of IPv6 brackets. Node's bind layer expects
|
|
4
|
+
* the bare address ("::1"), not the bracketed URL form ("[::1]"), so the same
|
|
5
|
+
* normalization must feed both the loopback check and the actual bind call.
|
|
6
|
+
* Otherwise a bracketed host can clear the F2 safety gate yet fail to bind.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeHostForBind(host: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* True only for genuine loopback hosts: "localhost", the IPv4 loopback block
|
|
11
|
+
* 127.0.0.0/8 (octets validated), IPv6 "::1", and IPv4-mapped IPv6 loopback
|
|
12
|
+
* "::ffff:127.x.x.x". "0.0.0.0", "::", and any LAN or public address are
|
|
13
|
+
* intentionally NOT loopback (F2).
|
|
14
|
+
*/
|
|
15
|
+
export declare function isLoopbackHost(host: string): boolean;
|
|
16
|
+
//# sourceMappingURL=net-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"net-host.d.ts","sourceRoot":"","sources":["../src/net-host.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAYD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASpD"}
|
package/dist/net-host.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a host string for binding and loopback comparison: trim, lowercase,
|
|
3
|
+
* and strip a single surrounding pair of IPv6 brackets. Node's bind layer expects
|
|
4
|
+
* the bare address ("::1"), not the bracketed URL form ("[::1]"), so the same
|
|
5
|
+
* normalization must feed both the loopback check and the actual bind call.
|
|
6
|
+
* Otherwise a bracketed host can clear the F2 safety gate yet fail to bind.
|
|
7
|
+
*/
|
|
8
|
+
export function normalizeHostForBind(host) {
|
|
9
|
+
return host.trim().toLowerCase().replace(/^\[/, "").replace(/\]$/, "");
|
|
10
|
+
}
|
|
11
|
+
// Strict dotted-quad IPv4 with every octet in 0-255. Kept dependency-free (no
|
|
12
|
+
// node:net) so this module stays usable from the isomorphic shared package.
|
|
13
|
+
// Rejects malformed values like "127.999.999.999" that a loose \d{1,3} regex
|
|
14
|
+
// would wrongly accept.
|
|
15
|
+
function isStrictIpv4(h) {
|
|
16
|
+
const m = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(h);
|
|
17
|
+
if (!m)
|
|
18
|
+
return false;
|
|
19
|
+
return m.slice(1).every((octet) => Number(octet) <= 255);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* True only for genuine loopback hosts: "localhost", the IPv4 loopback block
|
|
23
|
+
* 127.0.0.0/8 (octets validated), IPv6 "::1", and IPv4-mapped IPv6 loopback
|
|
24
|
+
* "::ffff:127.x.x.x". "0.0.0.0", "::", and any LAN or public address are
|
|
25
|
+
* intentionally NOT loopback (F2).
|
|
26
|
+
*/
|
|
27
|
+
export function isLoopbackHost(host) {
|
|
28
|
+
const h = normalizeHostForBind(host);
|
|
29
|
+
if (h === "localhost" || h === "::1")
|
|
30
|
+
return true;
|
|
31
|
+
if (isStrictIpv4(h))
|
|
32
|
+
return h.startsWith("127.");
|
|
33
|
+
if (h.startsWith("::ffff:")) {
|
|
34
|
+
const v4 = h.slice("::ffff:".length);
|
|
35
|
+
return isStrictIpv4(v4) && v4.startsWith("127.");
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=net-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"net-host.js","sourceRoot":"","sources":["../src/net-host.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACzE,CAAC;AAED,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,wBAAwB;AACxB,SAAS,YAAY,CAAC,CAAS;IAC7B,MAAM,CAAC,GAAG,8CAA8C,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjE,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrB,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,CAAC,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,YAAY,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACrC,OAAO,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/result.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ErrorJSON } from "./errors";
|
|
2
|
+
export interface ToolMeta {
|
|
3
|
+
duration_ms: number;
|
|
4
|
+
result_size: number;
|
|
5
|
+
overflow_bytes?: number;
|
|
6
|
+
explain?: unknown;
|
|
7
|
+
}
|
|
8
|
+
export interface ToolOk<T = unknown> {
|
|
9
|
+
ok: true;
|
|
10
|
+
data: T;
|
|
11
|
+
meta: ToolMeta;
|
|
12
|
+
}
|
|
13
|
+
export interface ToolErr {
|
|
14
|
+
ok: false;
|
|
15
|
+
error: ErrorJSON;
|
|
16
|
+
meta: ToolMeta;
|
|
17
|
+
}
|
|
18
|
+
export type ToolResult<T = unknown> = ToolOk<T> | ToolErr;
|
|
19
|
+
//# sourceMappingURL=result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AACD,MAAM,WAAW,MAAM,CAAC,CAAC,GAAG,OAAO;IACjC,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,EAAE,QAAQ,CAAC;CAChB;AACD,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;CAChB;AACD,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC"}
|
package/dist/result.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Vault registry id: lowercase slug. */
|
|
3
|
+
export declare const VaultId: z.ZodString;
|
|
4
|
+
/**
|
|
5
|
+
* Vault-relative path. Rejects absolute paths (POSIX and Windows drive paths)
|
|
6
|
+
* and any ".." segment. Backslashes are tolerated on input and normalized by
|
|
7
|
+
* the resolver; the byte-level guard stays conservative per G2.1.
|
|
8
|
+
*/
|
|
9
|
+
export declare const VaultPath: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
10
|
+
/** 32-char hex HITL elicit token (matches issueElicitToken: randomBytes(16).hex). */
|
|
11
|
+
export declare const ElicitToken: z.ZodString;
|
|
12
|
+
/** Cursor pagination inputs (G2.1 convention). */
|
|
13
|
+
export declare const Pagination: z.ZodObject<{
|
|
14
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
16
|
+
}, "strip", z.ZodTypeAny, {
|
|
17
|
+
limit?: number | undefined;
|
|
18
|
+
cursor?: string | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
limit?: number | undefined;
|
|
21
|
+
cursor?: string | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
export type PaginationInput = z.infer<typeof Pagination>;
|
|
24
|
+
/** Shared write options. `idempotency_key` is accepted as a forward-compat
|
|
25
|
+
* surface in M1 (replay lands with the Policy layer in a later milestone). */
|
|
26
|
+
export declare const WriteOptions: z.ZodObject<{
|
|
27
|
+
idempotency_key: z.ZodOptional<z.ZodString>;
|
|
28
|
+
create_dirs: z.ZodDefault<z.ZodBoolean>;
|
|
29
|
+
}, "strip", z.ZodTypeAny, {
|
|
30
|
+
create_dirs: boolean;
|
|
31
|
+
idempotency_key?: string | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
idempotency_key?: string | undefined;
|
|
34
|
+
create_dirs?: boolean | undefined;
|
|
35
|
+
}>;
|
|
36
|
+
export type WriteOptionsInput = z.infer<typeof WriteOptions>;
|
|
37
|
+
//# sourceMappingURL=primitives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/schemas/primitives.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,yCAAyC;AACzC,eAAO,MAAM,OAAO,aAI0C,CAAC;AAE/D;;;;GAIG;AACH,eAAO,MAAM,SAAS,yEAQnB,CAAC;AAEJ,qFAAqF;AACrF,eAAO,MAAM,WAAW,aAA+D,CAAC;AAExF,kDAAkD;AAClD,eAAO,MAAM,UAAU;;;;;;;;;EAGrB,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEzD;+EAC+E;AAC/E,eAAO,MAAM,YAAY;;;;;;;;;EAGvB,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Shared Zod primitives for the tool surface (G2.1 "Standard primitives").
|
|
2
|
+
// Reused across every vault-touching tool so path-safety and pagination are
|
|
3
|
+
// uniform. The traversal guard here is defense-in-depth; the filesystem
|
|
4
|
+
// resolver (packages/server/src/vault/paths.ts) re-checks real-path containment.
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
/** Vault registry id: lowercase slug. */
|
|
7
|
+
export const VaultId = z
|
|
8
|
+
.string()
|
|
9
|
+
.min(1)
|
|
10
|
+
.max(64)
|
|
11
|
+
.regex(/^[a-z0-9_-]+$/, "vault id must be a lowercase slug");
|
|
12
|
+
/**
|
|
13
|
+
* Vault-relative path. Rejects absolute paths (POSIX and Windows drive paths)
|
|
14
|
+
* and any ".." segment. Backslashes are tolerated on input and normalized by
|
|
15
|
+
* the resolver; the byte-level guard stays conservative per G2.1.
|
|
16
|
+
*/
|
|
17
|
+
export const VaultPath = z
|
|
18
|
+
.string()
|
|
19
|
+
.min(1)
|
|
20
|
+
.max(1024)
|
|
21
|
+
.refine((p) => !p.includes(".."), "path traversal rejected")
|
|
22
|
+
.refine((p) => !p.startsWith("/") && !p.startsWith("\\") && !/^[A-Za-z]:[\\/]/.test(p), "absolute paths rejected");
|
|
23
|
+
/** 32-char hex HITL elicit token (matches issueElicitToken: randomBytes(16).hex). */
|
|
24
|
+
export const ElicitToken = z.string().regex(/^[a-f0-9]{32}$/, "malformed elicit token");
|
|
25
|
+
/** Cursor pagination inputs (G2.1 convention). */
|
|
26
|
+
export const Pagination = z.object({
|
|
27
|
+
limit: z.number().int().positive().max(1000).optional(),
|
|
28
|
+
cursor: z.string().optional(),
|
|
29
|
+
});
|
|
30
|
+
/** Shared write options. `idempotency_key` is accepted as a forward-compat
|
|
31
|
+
* surface in M1 (replay lands with the Policy layer in a later milestone). */
|
|
32
|
+
export const WriteOptions = z.object({
|
|
33
|
+
idempotency_key: z.string().min(1).max(128).optional(),
|
|
34
|
+
create_dirs: z.boolean().default(true),
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=primitives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"primitives.js","sourceRoot":"","sources":["../../src/schemas/primitives.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,4EAA4E;AAC5E,wEAAwE;AACxE,iFAAiF;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,yCAAyC;AACzC,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC;KACrB,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,EAAE,CAAC;KACP,KAAK,CAAC,eAAe,EAAE,mCAAmC,CAAC,CAAC;AAE/D;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC;KACvB,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,IAAI,CAAC;KACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,yBAAyB,CAAC;KAC3D,MAAM,CACL,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAC9E,yBAAyB,CAC1B,CAAC;AAEJ,qFAAqF;AACrF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,gBAAgB,EAAE,wBAAwB,CAAC,CAAC;AAExF,kDAAkD;AAClD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;IACvD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC;AAGH;+EAC+E;AAC/E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACtD,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CACvC,CAAC,CAAC"}
|
package/dist/scopes.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const SCOPE_FAMILIES: readonly ["read", "write", "delete", "execute", "admin", "bulk"];
|
|
2
|
+
export type ScopeFamily = (typeof SCOPE_FAMILIES)[number];
|
|
3
|
+
export type Scope = string;
|
|
4
|
+
export declare const HITL_FLOOR_SCOPES: ReadonlySet<Scope>;
|
|
5
|
+
export declare const HITL_FLOOR_FAMILIES: readonly string[];
|
|
6
|
+
export declare function parseScope(s: Scope): {
|
|
7
|
+
family: string;
|
|
8
|
+
resource: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function grantsScope(granted: Iterable<Scope>, required: Scope): boolean;
|
|
11
|
+
export declare function grantsAll(granted: Iterable<Scope>, required: readonly Scope[]): boolean;
|
|
12
|
+
export declare function scopeRequiresHitl(scope: Scope): boolean;
|
|
13
|
+
export declare const MUTATING_FAMILIES: readonly string[];
|
|
14
|
+
export declare function isMutatingScope(scope: Scope): boolean;
|
|
15
|
+
export declare function scopeClassOf(requiredScopes: readonly Scope[]): string;
|
|
16
|
+
//# sourceMappingURL=scopes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scopes.d.ts","sourceRoot":"","sources":["../src/scopes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,kEAAmE,CAAC;AAC/F,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAC1D,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC;AAG3B,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,KAAK,CAG/C,CAAC;AAGH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAAwB,CAAC;AAE1E,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAKzE;AAGD,wBAAgB,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAK,GAAG,OAAO,CAS9E;AAGD,wBAAgB,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,SAAS,KAAK,EAAE,GAAG,OAAO,CAGvF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAGvD;AAGD,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EAA2C,CAAC;AAE3F,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAErD;AAWD,wBAAgB,YAAY,CAAC,cAAc,EAAE,SAAS,KAAK,EAAE,GAAG,MAAM,CAIrE"}
|
package/dist/scopes.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export const SCOPE_FAMILIES = ["read", "write", "delete", "execute", "admin", "bulk"];
|
|
2
|
+
// Scopes that always require a HITL elicit confirmation (G2.4 A.3 hardcoded floors).
|
|
3
|
+
export const HITL_FLOOR_SCOPES = new Set([
|
|
4
|
+
"admin:auth",
|
|
5
|
+
"write:templater",
|
|
6
|
+
]);
|
|
7
|
+
// Families where every member is a HITL floor.
|
|
8
|
+
export const HITL_FLOOR_FAMILIES = ["execute", "bulk"];
|
|
9
|
+
export function parseScope(s) {
|
|
10
|
+
if (s === "*")
|
|
11
|
+
return { family: "*", resource: "*" };
|
|
12
|
+
const i = s.indexOf(":");
|
|
13
|
+
if (i < 0)
|
|
14
|
+
return { family: s, resource: "*" };
|
|
15
|
+
return { family: s.slice(0, i), resource: s.slice(i + 1) };
|
|
16
|
+
}
|
|
17
|
+
// Does the granted set satisfy one required scope, honoring family/global wildcards?
|
|
18
|
+
export function grantsScope(granted, required) {
|
|
19
|
+
const req = parseScope(required);
|
|
20
|
+
for (const g of granted) {
|
|
21
|
+
if (g === "*")
|
|
22
|
+
return true;
|
|
23
|
+
const gp = parseScope(g);
|
|
24
|
+
if (gp.family !== "*" && gp.family !== req.family)
|
|
25
|
+
continue;
|
|
26
|
+
if (gp.resource === "*" || gp.resource === req.resource)
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
// AND across all required scopes.
|
|
32
|
+
export function grantsAll(granted, required) {
|
|
33
|
+
const set = granted instanceof Set ? granted : new Set(granted);
|
|
34
|
+
return required.every((r) => grantsScope(set, r));
|
|
35
|
+
}
|
|
36
|
+
export function scopeRequiresHitl(scope) {
|
|
37
|
+
if (HITL_FLOOR_SCOPES.has(scope))
|
|
38
|
+
return true;
|
|
39
|
+
return HITL_FLOOR_FAMILIES.includes(parseScope(scope).family);
|
|
40
|
+
}
|
|
41
|
+
// Scope families that mutate the vault; denied when an ACL is read-only.
|
|
42
|
+
export const MUTATING_FAMILIES = ["write", "delete", "bulk", "execute"];
|
|
43
|
+
export function isMutatingScope(scope) {
|
|
44
|
+
return MUTATING_FAMILIES.includes(parseScope(scope).family);
|
|
45
|
+
}
|
|
46
|
+
// Scope-class precedence for the dispatch rate-limiter gate (THE-210) and the `scope_class`
|
|
47
|
+
// metric label (G2.4). A tool's governing class is the most operationally significant family
|
|
48
|
+
// among its required scopes: a bulk_* tool (write:notes + bulk:notes) is governed by `bulk`,
|
|
49
|
+
// an execute tool by `execute`, an admin tool by `admin`, a delete-only tool by `delete`, and
|
|
50
|
+
// so on. `delete` sits below `admin` but above `write` so a destructive single-delete is
|
|
51
|
+
// throttled at its own tier (THE-212) while a bulk_delete still resolves to `bulk`. A family
|
|
52
|
+
// with no configured throttle tier is treated as unlimited (an unknown tier is never throttled).
|
|
53
|
+
const SCOPE_CLASS_PRECEDENCE = ["bulk", "execute", "admin", "delete", "write", "read"];
|
|
54
|
+
export function scopeClassOf(requiredScopes) {
|
|
55
|
+
const families = new Set(requiredScopes.map((s) => parseScope(s).family));
|
|
56
|
+
for (const cls of SCOPE_CLASS_PRECEDENCE)
|
|
57
|
+
if (families.has(cls))
|
|
58
|
+
return cls;
|
|
59
|
+
return requiredScopes[0] ? parseScope(requiredScopes[0]).family : "unknown";
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=scopes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scopes.js","sourceRoot":"","sources":["../src/scopes.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@the-40-thieves/obsidian-tc-shared",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Shared Zod schemas and types for obsidian-tc",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": ["dist", "README.md", "LICENSE"],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"typecheck": "tsc --noEmit",
|
|
13
|
+
"test": "vitest run --passWithNoTests"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"zod": "^3.23.0"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"typescript": "^5.7.0",
|
|
20
|
+
"vitest": "^2.1.0"
|
|
21
|
+
},
|
|
8
22
|
"repository": {
|
|
9
23
|
"type": "git",
|
|
10
|
-
"url": "
|
|
11
|
-
|
|
12
|
-
"bugs": {
|
|
13
|
-
"url": "https://github.com/suavecito585/obsidian-tc/issues"
|
|
24
|
+
"url": "https://github.com/The-40-Thieves/obsidian-tc.git",
|
|
25
|
+
"directory": "packages/shared"
|
|
14
26
|
},
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./package.json": "./package.json"
|
|
33
|
+
}
|
|
18
34
|
}
|