@hasna/skills 0.10.43 → 0.10.44
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 +53 -0
- package/bin/index.js +2377 -1617
- package/bin/mcp.js +19 -1
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.js +1435 -778
- package/dist/lib/agent-integration.d.ts +20 -4
- package/dist/lib/codex-native-skill-policy.d.ts +310 -0
- package/dist/lib/codex-native-trust.d.ts +49 -0
- package/dist/lib/codex-plugin-skill-controls.d.ts +13 -0
- package/dist/sdk/index.js +1674 -1017
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type CodexCorpusWriteOptions } from "./codex-corpus-write.js";
|
|
2
2
|
import { type ReviewedCodexSkillDenial } from "./codex-plugin-skill-controls.js";
|
|
3
|
+
import { type CodexNativeHookEnvelope, type ProcessInspector, type NativePolicyHelperRunner } from "./codex-native-skill-policy.js";
|
|
3
4
|
import { type CodexNativeSkillCatalog } from "./codex-native-skill-catalog.js";
|
|
4
5
|
import { type AgentDiscoveryBinding, type ReviewedDiscoveryInputs } from "./agent-discovery.js";
|
|
5
6
|
import { type IntegrationAgent } from "./agent-adapters.js";
|
|
@@ -222,16 +223,31 @@ export declare function archiveNativeSkills(inventory: NativeSkillEntry[], optio
|
|
|
222
223
|
targetCount: number;
|
|
223
224
|
};
|
|
224
225
|
};
|
|
225
|
-
/**
|
|
226
|
-
*
|
|
227
|
-
|
|
226
|
+
/** Native hook input for the Codex policy adapter. Only the Codex hook paths that
|
|
227
|
+
* receive native SessionStart/UserPromptSubmit input supply it; install-time and
|
|
228
|
+
* other guard calls never do. `inspector` is a test seam for process lineage. */
|
|
229
|
+
export interface CodexNativePolicyGuardInput extends CodexNativeHookEnvelope {
|
|
230
|
+
inspector?: ProcessInspector;
|
|
231
|
+
helperRunner?: NativePolicyHelperRunner; /** Absolute epoch ms by which the hook must answer; bounds the hash and helper. */
|
|
232
|
+
deadlineMs?: number;
|
|
233
|
+
}
|
|
234
|
+
interface ManagedBridgeOptions {
|
|
228
235
|
home?: string;
|
|
229
236
|
dataDir?: string;
|
|
230
237
|
projectDir?: string;
|
|
231
238
|
projectDirs?: string[];
|
|
232
239
|
profileId?: string;
|
|
233
240
|
codexDiscoveryRecovery?: CodexHookDiscoveryRecovery;
|
|
234
|
-
|
|
241
|
+
codexNativePolicy?: CodexNativePolicyGuardInput;
|
|
242
|
+
}
|
|
243
|
+
/** Package-classified installed-plugin content below the Codex plugin cache that
|
|
244
|
+
* a verified restricted policy cannot load. Classification is the existing plugin
|
|
245
|
+
* manifest identity and real-path binding, never a path prefix; user, repo and
|
|
246
|
+
* project copies, unclassified cache files and any allowed host path refuse. */
|
|
247
|
+
export declare function isInertCodexPluginCacheCopy(entry: NativeSkillEntry, cache: string, allowedHostPaths: readonly string[], read: (path: string) => string): boolean;
|
|
248
|
+
/** Run before any prompt context load. Missing ownership or reappearing native
|
|
249
|
+
* discovery files require repair; verified cache availability is not an override. */
|
|
250
|
+
export declare function assertManagedAgentBridge(agent: IntegrationAgent, options?: ManagedBridgeOptions): void;
|
|
235
251
|
export declare function normalizeAgentHookPrompt(agent: IntegrationAgent, event: string, prompt: string): string;
|
|
236
252
|
export declare function hookContextOutput(event: string, result: {
|
|
237
253
|
context: string;
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { type BigIntStats } from "node:fs";
|
|
2
|
+
export declare const CODEX_NATIVE_POLICY_CAPABILITY = "host-path-allowlist-v1";
|
|
3
|
+
export declare const CODEX_NATIVE_POLICY_RECEIPT_SCHEMA = "skills.codex-native-policy-acceptance/v1";
|
|
4
|
+
/** Loop safety for the parent walk. It is not a policy bound on launch depth:
|
|
5
|
+
* Unix hooks run through the configured shell (`-lc`, new session), which may
|
|
6
|
+
* exec into the command or keep wrappers, so the real chain length varies. */
|
|
7
|
+
export declare const CODEX_NATIVE_POLICY_ANCESTRY_SAFETY_HOPS = 64;
|
|
8
|
+
export type CodexNativeHookEvent = "SessionStart" | "UserPromptSubmit";
|
|
9
|
+
/** Exactly the fields the native hook emits (hook_runtime.rs, native_skill_policy_for_hook). */
|
|
10
|
+
export interface CodexNativeSkillPolicy {
|
|
11
|
+
capability: typeof CODEX_NATIVE_POLICY_CAPABILITY;
|
|
12
|
+
mode: "restricted";
|
|
13
|
+
allowedHostPaths: [string];
|
|
14
|
+
nonHostSources: "disabled";
|
|
15
|
+
processId: number;
|
|
16
|
+
effectiveConfigDigest: string;
|
|
17
|
+
}
|
|
18
|
+
export interface CodexNativeHookEnvelope {
|
|
19
|
+
event: CodexNativeHookEvent;
|
|
20
|
+
policy: unknown;
|
|
21
|
+
sessionId: unknown;
|
|
22
|
+
/** Present on UserPromptSubmit only; SessionStart input has no turn id. */
|
|
23
|
+
turnId?: unknown;
|
|
24
|
+
/** SHA-256 of the exact hook stdin bytes, for the authenticated channel binding. */
|
|
25
|
+
hookInputSha256?: unknown;
|
|
26
|
+
/** Inherited read end of the per-hook socketpair Codex passes to the hook
|
|
27
|
+
* child, for the authenticated channel binding. Not yet named by the native
|
|
28
|
+
* contract, so the hook does not supply it today. */
|
|
29
|
+
inheritedFd?: unknown;
|
|
30
|
+
}
|
|
31
|
+
/** Native Codex sets this only on the current hook child; it names the
|
|
32
|
+
* inherited read end of the per-hook socketpair (draft binding contract). */
|
|
33
|
+
export declare const CODEX_NATIVE_POLICY_FD_ENV = "CODEX_NATIVE_SKILL_POLICY_FD";
|
|
34
|
+
/** Map one native hook input object to the adapter envelope, exactly as the
|
|
35
|
+
* Codex `hook user-prompt` path does. Undefined means the input carries no
|
|
36
|
+
* native policy or is not a SessionStart/UserPromptSubmit input, so the guard
|
|
37
|
+
* keeps today's behaviour. `inputBytes` are the exact raw stdin bytes, hashed
|
|
38
|
+
* before any decoding; `input` must have been parsed from those same bytes. */
|
|
39
|
+
export declare function codexNativeHookEnvelopeFromInput(input: Record<string, unknown>, event: string, inputBytes: Buffer, inheritedFd?: string): CodexNativeHookEnvelope | undefined;
|
|
40
|
+
/** Injectable so tests can supply fake lineages; production uses the OS. */
|
|
41
|
+
export interface ProcessInspector {
|
|
42
|
+
platform: string;
|
|
43
|
+
arch: string;
|
|
44
|
+
/** The hook process itself. */
|
|
45
|
+
pid: number;
|
|
46
|
+
parentOf(pid: number): number | null;
|
|
47
|
+
/** Opaque start identity; two equal reads mean the same process incarnation. */
|
|
48
|
+
startTime(pid: number): string | null;
|
|
49
|
+
executablePath(pid: number): string | null;
|
|
50
|
+
}
|
|
51
|
+
/** Reviewed operator trust from the managed policy (`bridge.codexNativePolicy`). */
|
|
52
|
+
export interface CodexNativePolicyTrust {
|
|
53
|
+
executableDigests: Readonly<Record<string, readonly string[]>>;
|
|
54
|
+
}
|
|
55
|
+
/** What the native helper attests over the inherited channel (draft contract). */
|
|
56
|
+
export interface CodexNativePolicyAttestation {
|
|
57
|
+
schema: typeof CODEX_NATIVE_POLICY_PEER_SCHEMA;
|
|
58
|
+
peerProcessId: number;
|
|
59
|
+
}
|
|
60
|
+
export interface CodexNativePolicyVerification {
|
|
61
|
+
event: CodexNativeHookEvent;
|
|
62
|
+
sessionId: string;
|
|
63
|
+
turnId: string | null;
|
|
64
|
+
policy: CodexNativeSkillPolicy;
|
|
65
|
+
platform: string;
|
|
66
|
+
ancestryHops: number;
|
|
67
|
+
processStartTime: string;
|
|
68
|
+
executablePath: string;
|
|
69
|
+
executableSha256: string;
|
|
70
|
+
/** No-follow identity of the qualified executable taken before hashing; re-taken after the helper. */
|
|
71
|
+
executableWitness: ExecutableWitness;
|
|
72
|
+
bridge: {
|
|
73
|
+
path: string;
|
|
74
|
+
sha256: string;
|
|
75
|
+
};
|
|
76
|
+
attestation?: CodexNativePolicyAttestation;
|
|
77
|
+
}
|
|
78
|
+
export interface CodexNativePolicyAcceptedSkill {
|
|
79
|
+
path: string;
|
|
80
|
+
treeSha256: string;
|
|
81
|
+
}
|
|
82
|
+
export interface CodexNativePolicyAcceptance {
|
|
83
|
+
schema: typeof CODEX_NATIVE_POLICY_RECEIPT_SCHEMA;
|
|
84
|
+
acceptedAt: string;
|
|
85
|
+
event: CodexNativeHookEvent;
|
|
86
|
+
sessionId: string;
|
|
87
|
+
turnId: string | null;
|
|
88
|
+
process: {
|
|
89
|
+
id: number;
|
|
90
|
+
startTime: string;
|
|
91
|
+
executablePath: string;
|
|
92
|
+
executableSha256: string;
|
|
93
|
+
platform: string;
|
|
94
|
+
};
|
|
95
|
+
effectiveConfigDigest: string;
|
|
96
|
+
bridge: {
|
|
97
|
+
path: string;
|
|
98
|
+
sha256: string;
|
|
99
|
+
};
|
|
100
|
+
acceptedCache: CodexNativePolicyAcceptedSkill[];
|
|
101
|
+
attestation?: CodexNativePolicyAttestation;
|
|
102
|
+
}
|
|
103
|
+
/** Draft native helper transport: argv, bounded run, JSON attestation. */
|
|
104
|
+
export declare const CODEX_NATIVE_POLICY_PEER_SCHEMA = "native-hook-policy-peer-v1";
|
|
105
|
+
export declare const CODEX_NATIVE_POLICY_HELPER_TIMEOUT_MS = 5000;
|
|
106
|
+
export declare const CODEX_NATIVE_POLICY_HELPER_MAX_OUTPUT_BYTES: number;
|
|
107
|
+
/** Hook-deadline bounds: the helper gets min(5 s, remaining minus the margin);
|
|
108
|
+
* a first-run executable hash needs this much budget; below the minimum the
|
|
109
|
+
* adapter refuses fast instead of spawning anything. */
|
|
110
|
+
export declare const CODEX_NATIVE_POLICY_DEADLINE_MARGIN_MS = 1000;
|
|
111
|
+
export declare const CODEX_NATIVE_POLICY_HELPER_MIN_TIMEOUT_MS = 500;
|
|
112
|
+
export declare const CODEX_NATIVE_POLICY_FIRST_HASH_BUDGET_MS = 3000;
|
|
113
|
+
export interface NativePolicyHelperRequest {
|
|
114
|
+
executablePath: string;
|
|
115
|
+
fd: number;
|
|
116
|
+
expectedProcessId: number;
|
|
117
|
+
inputSha256: string;
|
|
118
|
+
timeoutMs: number;
|
|
119
|
+
maxOutputBytes: number;
|
|
120
|
+
}
|
|
121
|
+
export interface NativePolicyHelperResult {
|
|
122
|
+
exitCode: number | null;
|
|
123
|
+
stdout: Buffer;
|
|
124
|
+
timedOut: boolean;
|
|
125
|
+
oversized: boolean;
|
|
126
|
+
}
|
|
127
|
+
/** Injectable so tests can fake the helper; production spawns the verified binary. */
|
|
128
|
+
export type NativePolicyHelperRunner = (request: NativePolicyHelperRequest) => NativePolicyHelperResult;
|
|
129
|
+
export declare const CODEX_NATIVE_POLICY_EXECUTABLE_CACHE_SCHEMA = "skills.codex-native-policy-executable-cache/v1";
|
|
130
|
+
/** No-follow identity of the qualified executable file; the only thing cached. */
|
|
131
|
+
export interface ExecutableWitness {
|
|
132
|
+
dev: string;
|
|
133
|
+
ino: string;
|
|
134
|
+
size: string;
|
|
135
|
+
mtimeNs: string;
|
|
136
|
+
ctimeNs: string;
|
|
137
|
+
uid: string;
|
|
138
|
+
}
|
|
139
|
+
/** Absent trust is an empty set: every platform is unqualified and refuses.
|
|
140
|
+
* The pinned digests are reviewed operator configuration, never a package default. */
|
|
141
|
+
export declare function parseCodexNativePolicyTrust(value: unknown): CodexNativePolicyTrust;
|
|
142
|
+
/** Strict envelope parsing. Unknown keys, unknown capability, unrestricted mode
|
|
143
|
+
* and anything but the exact bridge document refuse. */
|
|
144
|
+
export declare function parseCodexNativeHookEnvelope(envelope: CodexNativeHookEnvelope, bridgeDocument: string): {
|
|
145
|
+
policy: CodexNativeSkillPolicy;
|
|
146
|
+
sessionId: string;
|
|
147
|
+
turnId: string | null;
|
|
148
|
+
hookInputSha256: string | null;
|
|
149
|
+
inheritedFd: number | null;
|
|
150
|
+
};
|
|
151
|
+
/** The owned bridge document: a regular file, no link in any component, its
|
|
152
|
+
* real path equal to its lexical path, and exactly the bytes the guard installs. */
|
|
153
|
+
export declare function verifyCodexNativeBridgeDocument(path: string, expectedContent: string, expectedSha256: string): {
|
|
154
|
+
path: string;
|
|
155
|
+
sha256: string;
|
|
156
|
+
};
|
|
157
|
+
/** Walk the real parent chain from the hook process to the root. The claimed
|
|
158
|
+
* consumer must appear as a strict ancestor. Only a cycle/loop guard bounds
|
|
159
|
+
* the walk; the expected launch-chain shape (which wrappers may sit between
|
|
160
|
+
* Codex and this hook) is pending from the native author and plugs in here as
|
|
161
|
+
* a predicate over the walked chain. */
|
|
162
|
+
export declare function verifyCodexNativeAncestry(inspector: ProcessInspector, processId: number): {
|
|
163
|
+
hops: number;
|
|
164
|
+
chain: number[];
|
|
165
|
+
startTime: string;
|
|
166
|
+
};
|
|
167
|
+
export declare function hashExecutableFile(path: string): string;
|
|
168
|
+
/** Accept only a regular file owned by root or the current user that neither
|
|
169
|
+
* group nor world can write. Pure over the no-follow stat so it is testable
|
|
170
|
+
* with synthetic owners. */
|
|
171
|
+
export declare function assertExecutableWitnessStat(stat: Pick<BigIntStats, "isFile" | "isSymbolicLink" | "uid" | "mode" | "dev" | "ino" | "size" | "mtimeNs" | "ctimeNs">, currentUid: number): ExecutableWitness;
|
|
172
|
+
/** No-follow witness of the path proc_pidpath reported: no component may be a
|
|
173
|
+
* link, and the file must satisfy assertExecutableWitnessStat. */
|
|
174
|
+
export declare function executableWitness(path: string): ExecutableWitness;
|
|
175
|
+
export declare function executableCachePath(dataDir: string): string;
|
|
176
|
+
/** Digest of the qualified executable through the artifact-identity cache.
|
|
177
|
+
* Only (path, dev, ino, size, mtimeNs, ctimeNs, uid) -> sha256 is cached, in
|
|
178
|
+
* process and optionally in a 0600 file under the Skills data dir. A witness
|
|
179
|
+
* that changes between before and after, or differs from the cached key, is
|
|
180
|
+
* re-hashed. Policy, attestation, session and turn results are never cached. */
|
|
181
|
+
export declare function qualifiedExecutableSha256(path: string, options?: {
|
|
182
|
+
dataDir?: string;
|
|
183
|
+
hasher?: (path: string) => string;
|
|
184
|
+
deadlineMs?: number; /** Test seam: the uid the cache file must be owned by (besides root). */
|
|
185
|
+
cacheOwnerUid?: number;
|
|
186
|
+
}): {
|
|
187
|
+
sha256: string;
|
|
188
|
+
witness: ExecutableWitness;
|
|
189
|
+
cached: boolean;
|
|
190
|
+
};
|
|
191
|
+
/** Bind the claimed process to its start identity and a pinned executable
|
|
192
|
+
* digest. The pin set is reviewed operator trust; an absent or empty set for
|
|
193
|
+
* this platform means the platform is unqualified and refuses. Linux stays
|
|
194
|
+
* unqualified until its artifact is reviewed. The helper cannot attest that it
|
|
195
|
+
* is itself reviewed, so this trust stays in the managed policy. */
|
|
196
|
+
export declare function verifyCodexNativeExecutable(inspector: ProcessInspector, processId: number, trust: CodexNativePolicyTrust, cache?: {
|
|
197
|
+
dataDir?: string;
|
|
198
|
+
hasher?: (path: string) => string;
|
|
199
|
+
deadlineMs?: number;
|
|
200
|
+
}, expectations?: {
|
|
201
|
+
ancestryStartTime?: string;
|
|
202
|
+
}): {
|
|
203
|
+
platform: string;
|
|
204
|
+
startTime: string;
|
|
205
|
+
executablePath: string;
|
|
206
|
+
executableSha256: string;
|
|
207
|
+
witness: ExecutableWitness;
|
|
208
|
+
};
|
|
209
|
+
/** The Skills data directory is the operator trust root: the managed policy
|
|
210
|
+
* that carries the reviewed executable digests, and the executable identity
|
|
211
|
+
* cache, must each be a regular file reached through no symlink, owned by the
|
|
212
|
+
* current user or root and writable by neither group nor world. Anything else
|
|
213
|
+
* fails the adapter closed. A writer with the same uid is outside this
|
|
214
|
+
* boundary. */
|
|
215
|
+
export declare function assertOperatorTrustRoot(dataDir: string): void;
|
|
216
|
+
/** Production helper runner: the verified binary, no shell, an allowlisted
|
|
217
|
+
* empty environment, cwd `/`, the inherited descriptor forwarded as fd 3, and
|
|
218
|
+
* bounded time and output. Bun.spawnSync accepts a fourth stdio entry, which
|
|
219
|
+
* dup2s that descriptor to 3 in the child (measured on bun 1.3.14). */
|
|
220
|
+
export declare function runCodexNativePolicyHelper(request: NativePolicyHelperRequest): NativePolicyHelperResult;
|
|
221
|
+
/** Authenticated channel binding, against the frozen native source
|
|
222
|
+
* (native-hook-policy-peer-v1; "line" numbers below index the native
|
|
223
|
+
* producer's hook-policy-peer patch as reviewed):
|
|
224
|
+
* - the hook runner creates a Unix socketpair per invocation (line 296),
|
|
225
|
+
* forwards the receiver to the hook child (line 171) and names it in
|
|
226
|
+
* CODEX_NATIVE_SKILL_POLICY_FD (lines 172-175, constant at line 264);
|
|
227
|
+
* - the verifier is `<codex> debug verify-hook-policy --fd <i32>
|
|
228
|
+
* --expected-process-id <u32> --input-sha256 <hex>` (lines 88-97, dispatch
|
|
229
|
+
* lines 102-103), dispatched in main before config, auth-home or session
|
|
230
|
+
* setup (lines 55-58); it requires fd > 2 (line 449), a positive pid
|
|
231
|
+
* (line 450) and a lowercase 64-hex digest (line 456);
|
|
232
|
+
* - success writes one compact JSON object to stdout followed by a newline and
|
|
233
|
+
* exits 0 (lines 56-58): {"schema":"native-hook-policy-peer-v1",
|
|
234
|
+
* "peerProcessId":<kernel peer pid>,"stdinSha256":<the digest>,
|
|
235
|
+
* "policy":<the native_skill_policy the producer emitted>} (lines 546-550,
|
|
236
|
+
* schema at line 263); any failure returns an error from main, so the
|
|
237
|
+
* process exits non-zero with the message on stderr and nothing on stdout;
|
|
238
|
+
* - the producer hashes the exact bytes it wrote to the hook's stdin,
|
|
239
|
+
* lowercase hex (lines 286-288), and the verifier compares it with
|
|
240
|
+
* --input-sha256 (line 536), so the hook must hash its raw stdin bytes;
|
|
241
|
+
* - the verifier checks the kernel peer before and after a fresh random
|
|
242
|
+
* challenge (lines 466-469, 490-491, 517-519, 526-528); Linux also
|
|
243
|
+
* authenticates every response chunk's writer through SCM_CREDENTIALS.
|
|
244
|
+
* A creator-pid-only binding was rejected (NO_GO: pre-exec forgery
|
|
245
|
+
* reproduced); the fresh challenge plus actual-writer verification is the
|
|
246
|
+
* correction.
|
|
247
|
+
* The hook forwards the descriptor to the QUALIFIED ancestor's own executable
|
|
248
|
+
* (the digest-verified path, never PATH) as fd 3, with no shell, an empty
|
|
249
|
+
* environment, cwd `/` and bounded time and output, and accepts the
|
|
250
|
+
* attestation only when every field matches. The proof is never cached:
|
|
251
|
+
* once per invocation, SessionStart included. The channel pre-check here is
|
|
252
|
+
* fstat only; the socket semantics are enforced by the verifier itself. */
|
|
253
|
+
export declare function verifyCodexNativeChannelBinding(options: {
|
|
254
|
+
executablePath: string;
|
|
255
|
+
inheritedFd: number | null;
|
|
256
|
+
expectedProcessId: number;
|
|
257
|
+
expectedStartTime: string;
|
|
258
|
+
expectedWitness?: ExecutableWitness;
|
|
259
|
+
inputSha256: string | null;
|
|
260
|
+
emittedPolicy: unknown;
|
|
261
|
+
inspector: ProcessInspector;
|
|
262
|
+
runner?: NativePolicyHelperRunner;
|
|
263
|
+
timeoutMs?: number;
|
|
264
|
+
maxOutputBytes?: number;
|
|
265
|
+
deadlineMs?: number;
|
|
266
|
+
}): CodexNativePolicyAttestation;
|
|
267
|
+
/** Required acceptance gate: the authenticated channel binding of the native
|
|
268
|
+
* contract, run with the qualified ancestor's verified executable and its
|
|
269
|
+
* witness, its start time, the raw stdin digest, the inherited descriptor, the
|
|
270
|
+
* emitted policy and the remaining hook budget. */
|
|
271
|
+
export declare function assertAuthenticatedChannelBinding(binding: {
|
|
272
|
+
processId: number;
|
|
273
|
+
hookInputSha256: string | null;
|
|
274
|
+
inheritedFd: number | null;
|
|
275
|
+
verification: CodexNativePolicyVerification;
|
|
276
|
+
emittedPolicy: unknown;
|
|
277
|
+
inspector: ProcessInspector;
|
|
278
|
+
runner?: NativePolicyHelperRunner;
|
|
279
|
+
deadlineMs?: number;
|
|
280
|
+
}): CodexNativePolicyAttestation;
|
|
281
|
+
/** Full adapter verification. Every step refuses with a reason. Order: trust
|
|
282
|
+
* configuration, envelope, bridge, ancestry, executable digest (reviewed trust),
|
|
283
|
+
* then the authenticated channel binding, once per invocation. */
|
|
284
|
+
export declare function verifyCodexNativeSkillPolicy(options: {
|
|
285
|
+
envelope: CodexNativeHookEnvelope;
|
|
286
|
+
bridgeDocument: string;
|
|
287
|
+
expectedBridgeContent: string;
|
|
288
|
+
expectedBridgeSha256: string;
|
|
289
|
+
trust?: unknown;
|
|
290
|
+
inspector?: ProcessInspector;
|
|
291
|
+
dataDir?: string;
|
|
292
|
+
executableHasher?: (path: string) => string;
|
|
293
|
+
helperRunner?: NativePolicyHelperRunner;
|
|
294
|
+
deadlineMs?: number;
|
|
295
|
+
}): CodexNativePolicyVerification;
|
|
296
|
+
/** Darwin: libproc through bun:ffi. proc_pidinfo(PROC_PIDTBSDINFO) yields the
|
|
297
|
+
* parent pid and start time; proc_pidpath yields the executable path. Layout
|
|
298
|
+
* from the SDK's sys/proc_info.h (struct proc_bsdinfo, 136 bytes): pbi_pid at
|
|
299
|
+
* 12, pbi_ppid at 16, pbi_start_tvsec at 120, pbi_start_tvusec at 128. */
|
|
300
|
+
export declare function darwinProcessInspector(): ProcessInspector;
|
|
301
|
+
/** Linux: procfs. The parent pid and start time (clock ticks since boot) come
|
|
302
|
+
* from /proc/<pid>/stat after the bracketed command name; the executable from
|
|
303
|
+
* /proc/<pid>/exe. Linux remains unqualified until its artifact is reviewed. */
|
|
304
|
+
export declare function linuxProcessInspector(): ProcessInspector;
|
|
305
|
+
export declare function defaultProcessInspector(): ProcessInspector;
|
|
306
|
+
export declare function codexNativePolicyReceiptPath(dataDir: string): string;
|
|
307
|
+
/** Write the provenance receipt for one accepted hook: mode 0600, exclusive
|
|
308
|
+
* no-follow temporary file, then rename. Any failure throws, and the caller
|
|
309
|
+
* treats that as a refusal. Reachable only after the channel binding passes. */
|
|
310
|
+
export declare function recordCodexNativePolicyAcceptance(dataDir: string, verification: CodexNativePolicyVerification, accepted: readonly CodexNativePolicyAcceptedSkill[]): string;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type AgentIntegrationPlan } from "./agent-integration.js";
|
|
2
|
+
export declare const CODEX_NATIVE_TRUST_PLAN_SCHEMA = "skills.codex-native-trust-plan/v1";
|
|
3
|
+
export declare const CODEX_NATIVE_TRUST_RECEIPT_SCHEMA = "skills.codex-native-trust-receipt/v1";
|
|
4
|
+
export interface CodexNativeTrustPlan {
|
|
5
|
+
schema: typeof CODEX_NATIVE_TRUST_PLAN_SCHEMA;
|
|
6
|
+
dataDir: string;
|
|
7
|
+
policyPath: string;
|
|
8
|
+
platform: string;
|
|
9
|
+
digestsBefore: string[];
|
|
10
|
+
digestsAfter: string[];
|
|
11
|
+
policySha256Before: string;
|
|
12
|
+
policySha256After: string;
|
|
13
|
+
/** The ordinary plan the existing apply path writes: at most one change, the managed policy. */
|
|
14
|
+
plan: AgentIntegrationPlan;
|
|
15
|
+
}
|
|
16
|
+
export interface CodexNativeTrustReceipt {
|
|
17
|
+
schema: typeof CODEX_NATIVE_TRUST_RECEIPT_SCHEMA;
|
|
18
|
+
applied: boolean;
|
|
19
|
+
platform: string;
|
|
20
|
+
digestsBefore: string[];
|
|
21
|
+
digestsAfter: string[];
|
|
22
|
+
policySha256Before: string;
|
|
23
|
+
policySha256After: string;
|
|
24
|
+
changes: string[];
|
|
25
|
+
backup?: {
|
|
26
|
+
path: string;
|
|
27
|
+
sha256: string;
|
|
28
|
+
verified: true;
|
|
29
|
+
};
|
|
30
|
+
readback?: {
|
|
31
|
+
policySha256: string;
|
|
32
|
+
digests: string[];
|
|
33
|
+
verified: true;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Validate the request, the current policy and its SHA, and build the plan. Read-only. */
|
|
37
|
+
export declare function planCodexNativeTrust(options: {
|
|
38
|
+
dataDir?: string;
|
|
39
|
+
platform: string;
|
|
40
|
+
digests: readonly string[];
|
|
41
|
+
expectedPolicySha256: string;
|
|
42
|
+
}): CodexNativeTrustPlan;
|
|
43
|
+
export declare function previewCodexNativeTrust(plan: CodexNativeTrustPlan): CodexNativeTrustReceipt;
|
|
44
|
+
/** Write the planned trust. The current bytes are re-checked against the
|
|
45
|
+
* expected SHA immediately before the existing apply path replaces them; that
|
|
46
|
+
* path compares the exact bytes again, backs the original up, replaces the
|
|
47
|
+
* file atomically at 0600 and restores the original on failure. The backup
|
|
48
|
+
* and the result are read back and verified before a receipt is returned. */
|
|
49
|
+
export declare function applyCodexNativeTrust(plan: CodexNativeTrustPlan, expectedPolicySha256: string): CodexNativeTrustReceipt;
|
|
@@ -32,6 +32,19 @@ export interface CodexPluginSourceInput {
|
|
|
32
32
|
sourceSha256: string;
|
|
33
33
|
}
|
|
34
34
|
type Read = (path: string) => string;
|
|
35
|
+
export interface CodexPluginCacheDocumentIdentity {
|
|
36
|
+
name: string;
|
|
37
|
+
namespace: string;
|
|
38
|
+
pluginId: string;
|
|
39
|
+
pluginParent: string;
|
|
40
|
+
root: string;
|
|
41
|
+
manifestSha256: string;
|
|
42
|
+
}
|
|
43
|
+
/** Classify one cache document as installed-plugin content through the same
|
|
44
|
+
* manifest identity, capability review and real-path binding the reviewed
|
|
45
|
+
* predicates use. This is identity only: it consults no enable rule, reviewed
|
|
46
|
+
* control or native catalog, and it never admits anything by itself. */
|
|
47
|
+
export declare function classifyCodexPluginCacheDocument(document: string, cache: string, read: Read): CodexPluginCacheDocumentIdentity | null;
|
|
35
48
|
/** Establish the reviewed denial/skills-only role for an exact remote parent.
|
|
36
49
|
* Walk every ancestor: a dangling alias or non-directory is never absence. */
|
|
37
50
|
export declare function reviewedDisabledCodexPluginParent(cache: string, parent: string, controls: CodexPluginSkillControl[], rules: unknown): boolean;
|