approval-md 0.4.3 → 0.4.6
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/SPEC.md +13 -2
- package/dist/src/channels/telegram.d.ts +105 -31
- package/dist/src/channels/telegram.js +157 -81
- package/dist/src/channels/telegram.js.map +1 -1
- package/dist/src/cli/channel-telegram.d.ts +100 -35
- package/dist/src/cli/channel-telegram.js +216 -119
- package/dist/src/cli/channel-telegram.js.map +1 -1
- package/dist/src/cli/doctor.js +33 -13
- package/dist/src/cli/doctor.js.map +1 -1
- package/dist/src/cli/help.js +3 -3
- package/dist/src/cli/hook-exec-code.d.ts +150 -0
- package/dist/src/cli/hook-exec-code.js +357 -0
- package/dist/src/cli/hook-exec-code.js.map +1 -0
- package/dist/src/cli/hook.d.ts +125 -1
- package/dist/src/cli/hook.js +2177 -107
- package/dist/src/cli/hook.js.map +1 -1
- package/dist/src/cli/wordmark.d.ts +2 -2
- package/dist/src/cli/wordmark.js +2 -2
- package/dist/src/core/command-class.d.ts +368 -1
- package/dist/src/core/command-class.js +2830 -93
- package/dist/src/core/command-class.js.map +1 -1
- package/dist/src/core/date-argv.d.ts +83 -0
- package/dist/src/core/date-argv.js +212 -0
- package/dist/src/core/date-argv.js.map +1 -0
- package/dist/src/core/exec-code.d.ts +77 -0
- package/dist/src/core/exec-code.js +60 -0
- package/dist/src/core/exec-code.js.map +1 -0
- package/dist/src/core/git-push-argv.d.ts +111 -0
- package/dist/src/core/git-push-argv.js +375 -0
- package/dist/src/core/git-push-argv.js.map +1 -0
- package/dist/src/core/harness-version.d.ts +71 -30
- package/dist/src/core/harness-version.js +101 -34
- package/dist/src/core/harness-version.js.map +1 -1
- package/dist/src/core/policy-load.d.ts +8 -0
- package/dist/src/core/policy-load.js.map +1 -1
- package/dist/src/core/read-scope.js +1 -0
- package/dist/src/core/read-scope.js.map +1 -1
- package/dist/src/core/sysinfo-argv.d.ts +48 -0
- package/dist/src/core/sysinfo-argv.js +340 -0
- package/dist/src/core/sysinfo-argv.js.map +1 -0
- package/dist/src/daemon/git-evidence.d.ts +2 -2
- package/dist/src/daemon/git-evidence.js +1 -1
- package/docs/README-extended.md +3 -2
- package/docs/cli-reference.md +20 -7
- package/package.json +2 -2
- package/schema/event.schema.json +1 -1
- package/schema/fixtures/policy/invalid/exec-code-custody-boolean.json +11 -0
- package/schema/fixtures/policy/invalid/exec-code-execute-code-value.json +11 -0
- package/schema/fixtures/policy/invalid/exec-code-unknown-key.json +12 -0
- package/schema/fixtures/policy/valid/exec-code-both.json +17 -0
- package/schema/fixtures/policy/valid/exec-code-custody.json +11 -0
- package/schema/policy.schema.json +23 -0
package/dist/src/cli/hook.d.ts
CHANGED
|
@@ -321,6 +321,28 @@ export declare const HOOK_DENY_CODES: readonly [
|
|
|
321
321
|
* say about bytes it could see. Here there are no bytes to see.
|
|
322
322
|
*/
|
|
323
323
|
"hook-hermes-execute-code-unbound",
|
|
324
|
+
/**
|
|
325
|
+
* An opaque program (`python3 -c`, `node -e` and kin, an interpreter running a
|
|
326
|
+
* file that is not a skill script, or a Hermes `execute_code` call with
|
|
327
|
+
* `exec.code.execute_code: hooked`) under a policy that NAMES the `exec.code`
|
|
328
|
+
* class but does not declare `exec.code.custody: attested` (APRV-510).
|
|
329
|
+
*
|
|
330
|
+
* Distinct from `hook-opaque`, and the distinction is the repair: that one
|
|
331
|
+
* says rewrite the command, this one says the operator has asked for the
|
|
332
|
+
* class and the one line that opens it is missing. A policy that does not
|
|
333
|
+
* name `exec.code` at all keeps today's refusal byte for byte, so this code
|
|
334
|
+
* is never a surprise to an operator who has not opted in. Nothing appends.
|
|
335
|
+
*/
|
|
336
|
+
"hook-exec-code-custody-unattested",
|
|
337
|
+
/**
|
|
338
|
+
* An `exec.code` file program this hook cannot read and hash (APRV-510): it
|
|
339
|
+
* is absent, unreadable by this process (EACCES under co-location), not a
|
|
340
|
+
* regular file, too large, or relative after a `cd` the hook cannot place.
|
|
341
|
+
* A record of an opaque program binds its hash, and a program whose bytes
|
|
342
|
+
* cannot be read is one nothing could bind, so it is refused rather than
|
|
343
|
+
* recorded without one. Nothing appends.
|
|
344
|
+
*/
|
|
345
|
+
"hook-exec-code-unreadable",
|
|
324
346
|
/** Malformed hook input, or a log/filesystem fact that stopped the check. */
|
|
325
347
|
"hook-io"];
|
|
326
348
|
export type HookDenyCode = (typeof HOOK_DENY_CODES)[number];
|
|
@@ -725,6 +747,95 @@ export declare function resolveReadRoots(cwd: string, gateRoot: string, declared
|
|
|
725
747
|
* "absent yields today's answer" the classifier context promises.
|
|
726
748
|
*/
|
|
727
749
|
export declare function refineReadScope(result: CommandClassification, roots: readonly string[], cwd: string): RefinedClassification;
|
|
750
|
+
/** The rule a credential read found by resolving its path reports. */
|
|
751
|
+
export declare const CREDENTIAL_RESOLVED_RULE = "credential-path-resolved";
|
|
752
|
+
/**
|
|
753
|
+
* Every credential file a command reads once its paths are resolved the way
|
|
754
|
+
* the shell and the filesystem will resolve them (APRV-522, M4 and M5).
|
|
755
|
+
*
|
|
756
|
+
* The pure classifier judges the words as written. A word written relative
|
|
757
|
+
* after a `cd`, through a symlinked parent, as a glob, or inside a `$(…)` does
|
|
758
|
+
* not carry the segments the credential rule matches, so it was `read.shell`
|
|
759
|
+
* through the Claude Code hook (a relative read after a `cd` into the approval
|
|
760
|
+
* home, a read through a symlinked alias of it, a glob or `<` target naming a
|
|
761
|
+
* file in it), and through the Hermes hook too when the reader's segment also
|
|
762
|
+
* wrote, or the reader sat inside a substitution.
|
|
763
|
+
*
|
|
764
|
+
* Every adapter and `hook classify` reach this through {@link classifyForHook}.
|
|
765
|
+
* What is judged, per segment, whatever class the segment took:
|
|
766
|
+
*
|
|
767
|
+
* - the words {@link credentialReadWords} says the binary reads (the pure
|
|
768
|
+
* rule's own list: positionals, option-embedded values, git `<rev>:<path>`),
|
|
769
|
+
* and every `<` target;
|
|
770
|
+
* - each word expanded ({@link expandHookWord}, brace lists included), then
|
|
771
|
+
* landed from every directory the command may be in: lexically
|
|
772
|
+
* ({@link canonicalPath}) and physically ({@link physicalLanding}), a glob
|
|
773
|
+
* expanded against its directory (or, where that is unknown, judged by
|
|
774
|
+
* whether its pattern could name a credential);
|
|
775
|
+
* - a directory handed to a recursive reader or a directory copier, when it
|
|
776
|
+
* {@link holdsCredentials}. git and diff count as recursive readers here
|
|
777
|
+
* (fix round 1, S): git's no-index grep and diff walk a directory, and diff
|
|
778
|
+
* compares a directory's files. A recursive search also reads the working
|
|
779
|
+
* directory (fix round 1, M-E), whether or not it names a path, because
|
|
780
|
+
* which of its words are option values cannot be known for every reader;
|
|
781
|
+
* - a one-operand link or copy keeps its only operand as a read, because the
|
|
782
|
+
* destination is the working directory (fix round 1, M-F);
|
|
783
|
+
* - `cd` and `pushd` move the directory for later segments, the directories
|
|
784
|
+
* before and after both kept (a `cd` may fail, or sit behind `||`), each as
|
|
785
|
+
* spelled and with its symlinks resolved (fix round 2). After a `cd` this
|
|
786
|
+
* hook cannot resolve, every later RELATIVE read word is a credential read:
|
|
787
|
+
* where it lands is unknown, and it may be the vault. A `cd` is
|
|
788
|
+
* unresolvable when its operand is a variable, `-`, a glob or a brace list,
|
|
789
|
+
* or a tilde prefix this hook does not expand; when it carries an
|
|
790
|
+
* assignment prefix; and in the argv shapes {@link cdTarget} lists. `popd`
|
|
791
|
+
* is always unresolvable. (A segment that reassigns `HOME` or `CDPATH` on
|
|
792
|
+
* its own, `export`, `unset` or `read` of either included, is refused by the
|
|
793
|
+
* classifier before this pass runs.)
|
|
794
|
+
* - a relative operand that does not open with `./` or `../` may be found
|
|
795
|
+
* through a `CDPATH` this hook cannot see (fix round 1, M-B). Since fix
|
|
796
|
+
* round 2 that does not make the directory wholly unknown: the `cd` also
|
|
797
|
+
* lands at `<unknown prefix>/<operand>`, and each later relative word is a
|
|
798
|
+
* credential read there only when {@link steeredReadCouldNameCredential}
|
|
799
|
+
* says that path could name credential material or a gate home. A
|
|
800
|
+
* recursive reader, a word holding `..` and a `**` glob are credential
|
|
801
|
+
* reads there, since what they reach below an unknown directory cannot be
|
|
802
|
+
* bounded.
|
|
803
|
+
* - the body of every `$(…)`, and the script of every login-shell wrapper the
|
|
804
|
+
* classifier unwraps (fix round 1, M-A), walked the same way from the
|
|
805
|
+
* directory it runs in. A known shell handed an inline script in any other
|
|
806
|
+
* shape is a credential read, since what it reads cannot be judged;
|
|
807
|
+
* - past {@link BRACE_WORD_CAP} brace words, or {@link SUBSTITUTION_DEPTH_CAP}
|
|
808
|
+
* levels of nesting, a credential read (fix round 1, M-D).
|
|
809
|
+
*
|
|
810
|
+
* A word opening with a tilde prefix this hook does not expand (`~+`, `~-`,
|
|
811
|
+
* `~name`) is a credential read (fix round 1, M-C). A relative word read after an
|
|
812
|
+
* unresolvable `cd` is a credential read even when it holds a `$` this hook
|
|
813
|
+
* cannot expand (fix round 1, S-2). Otherwise a word left with such a `$` (a
|
|
814
|
+
* variable, or the substitution sentinel a `$(…)` leaves) is judged here for
|
|
815
|
+
* every adapter (APRV-524): by its text, by its literal prefix landed from
|
|
816
|
+
* each working directory, and, when its last component is the unresolved
|
|
817
|
+
* one, as a read of whatever that prefix holds, so a home or a directory that
|
|
818
|
+
* holds credentials makes it a credential read. A word holding the sentinel is
|
|
819
|
+
* judged once more with every sentinel removed, as a resolved path (the
|
|
820
|
+
* reading before APRV-511), so an empty substitution is judged too. The Hermes
|
|
821
|
+
* disk pass also fails closed on every recursive reader of such a word; this
|
|
822
|
+
* pass does not. Beyond that, a path held in a variable (which may be empty)
|
|
823
|
+
* or produced by a substitution's output is the accepted limit.
|
|
824
|
+
*
|
|
825
|
+
* `cwd` may name several directories (fix round 1, S-1): every one is a place
|
|
826
|
+
* the command may start in, and each is judged.
|
|
827
|
+
*/
|
|
828
|
+
export declare function credentialReadLandings(command: string, cwd: string | readonly string[], env?: NodeJS.ProcessEnv): Array<{
|
|
829
|
+
segment: string;
|
|
830
|
+
path: string;
|
|
831
|
+
}>;
|
|
832
|
+
/**
|
|
833
|
+
* Add an `account.credential` segment for every credential read
|
|
834
|
+
* {@link credentialReadLandings} finds that the text did not already name
|
|
835
|
+
* (APRV-522). Only ever adds: the segment's own class stays, and the
|
|
836
|
+
* credential read rides beside it in the shape the classifier's `also` has.
|
|
837
|
+
*/
|
|
838
|
+
export declare function refineCredentialReads(result: CommandClassification, command: string, cwd: string | readonly string[], env?: NodeJS.ProcessEnv): RefinedClassification;
|
|
728
839
|
/**
|
|
729
840
|
* The roots a write may land in, resolved.
|
|
730
841
|
*
|
|
@@ -798,7 +909,20 @@ export declare function refineSkillScripts(result: CommandClassification, cwd: s
|
|
|
798
909
|
* resolved gate scope wants and what this classifier did before the field
|
|
799
910
|
* existed.
|
|
800
911
|
*/
|
|
801
|
-
export declare function classifyForHook(command: string, protectedPaths: readonly ProtectedPathEntry[], cwd: string, readRoots?: readonly string[]
|
|
912
|
+
export declare function classifyForHook(command: string, protectedPaths: readonly ProtectedPathEntry[], cwd: string, readRoots?: readonly string[],
|
|
913
|
+
/**
|
|
914
|
+
* May an opaque program classify `exec.code`? (APRV-510.) `true` only when
|
|
915
|
+
* the loaded policy opens the class ({@link execCodeGate}); the default is
|
|
916
|
+
* today's answer, a refusal.
|
|
917
|
+
*/
|
|
918
|
+
execCode?: boolean,
|
|
919
|
+
/**
|
|
920
|
+
* Further directories the command may start in, judged by the credential
|
|
921
|
+
* pass only (APRV-522 fix round 1, S-1): the envelope's `cwd` where the
|
|
922
|
+
* harness sends no per-call directory. It only ever adds reads, so a stale
|
|
923
|
+
* or absent directory costs nothing.
|
|
924
|
+
*/
|
|
925
|
+
credentialCwds?: readonly string[]): RefinedClassification;
|
|
802
926
|
/**
|
|
803
927
|
* What the classifier made of a command (APRV-91 #9).
|
|
804
928
|
*
|