@bitspark/archon-cli 0.6.1

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.
@@ -0,0 +1,148 @@
1
+ /** Where the offers form writes its interactive lines and how it waits, injected so a test can
2
+ * pin the code and the page mark on stderr, the pacing, and the ledger's wall-clock end —
3
+ * without sleeping through the pacing or patching process streams. `run` hands the real ones. */
4
+ export interface LoginIo {
5
+ writeErr: (text: string) => void;
6
+ sleep: (seconds: number) => Promise<void>;
7
+ /** Seconds since the Unix epoch. */
8
+ now: () => number;
9
+ }
10
+ /** What the service answers on GET <audience>/login/<id>.
11
+ *
12
+ * NOTE the absent field: there is no `audience` here, by design (Finding 1). */
13
+ export interface LoginRequest {
14
+ id: string;
15
+ /** hex */
16
+ nonce: string;
17
+ /** canonical key text, ed25519:<hex> */
18
+ browser: string;
19
+ /** ordered, verbatim, displayed to the person */
20
+ scope: string[];
21
+ /** seconds */
22
+ valid_for: number;
23
+ /** RFC 3339; when the REQUEST dies, not the delegation */
24
+ expires?: string;
25
+ }
26
+ /** What we POST to <audience>/login/<id>/answer. */
27
+ export interface LoginAnswer {
28
+ principal: string;
29
+ possession: string;
30
+ authority: string;
31
+ }
32
+ /** WHICH custody will sign. Decided at flag-parse time — before the audience is derived —
33
+ * so the statement can name it and a bad choice is refused before anything is fetched or
34
+ * shown. */
35
+ export interface LoginSource {
36
+ seedHex?: string;
37
+ keyFile?: string;
38
+ seedFile?: string;
39
+ /** A NAME in the store, never a principal (ADR 0007 §A). Set by --key, or by the store's
40
+ * default pointer when no source flag was given. */
41
+ storeKey?: string;
42
+ }
43
+ /** Settles the source: exactly one flag, or none and the store's default. It never guesses
44
+ * a seed file — the only fallback is the pointer the person set with `archon key default`.
45
+ * A named store key is checked to EXIST here (a stat, opening nothing), so a typo is
46
+ * refused before a pointless fetch; the password and the unlock still wait for consent. */
47
+ export declare function decideLoginSource(src: LoginSource): void;
48
+ /** Entry point. The order is the security order and is not an accident: derive the
49
+ * audience, fetch, validate, SHOW, confirm, only then unlock and sign.
50
+ *
51
+ * Everything decidable WITHOUT the network — which custody signs, whether the flags agree,
52
+ * whether a named store key exists, whether the authority file is readable — is decided
53
+ * first, so those refusals land before a request is made and before the person reads a
54
+ * statement they could not have signed.
55
+ *
56
+ * `write` is where the statement and the outcome go — stdout by default, and injectable so
57
+ * a test can pin what a person would have seen WITHOUT patching process.stdout.write. Under
58
+ * `node --test` the test file is a child that reports to the runner over its own stdout, so
59
+ * a patch there swallows the report and silently drops tests from the run. */
60
+ export declare function run(args: string[], write?: (text: string) => void, io?: LoginIo): Promise<void>;
61
+ /** Refuse a malformed request BEFORE anything is displayed, so the person is never shown a
62
+ * statement built from junk. Every refusal names the field. */
63
+ export declare function validateLoginRequest(r: LoginRequest, wantId: string): void;
64
+ /** EXACTLY what the person is asked to approve, and the text all three lanes must print
65
+ * byte-identically. nowSeconds is a parameter so the wall-clock end is testable. */
66
+ export declare function renderStatement(audience: string, r: LoginRequest, nowSeconds: number, keySource: string): string;
67
+ /** The offers form's counterpart (docs/login.md §4.1 rule 4): the same fields as the
68
+ * statement, printed AFTER answering rather than before signing, because in that form nobody
69
+ * confirmed — the person typed the scope and the audience is the CLI's own. It names K as the
70
+ * request delivered it, the source that signed, and the service's verdict (`undefined` for an
71
+ * accepted answer, else the code). Never the code: the ledger goes to stdout, and stdout may
72
+ * be a log. */
73
+ export declare function renderLedger(audience: string, r: LoginRequest, nowSeconds: number, keySource: string, refused: string | undefined): string;
74
+ /** Name the custody the signature will come from, for the last line of the statement
75
+ * (seat:cca ruling, 2026-09-10).
76
+ *
77
+ * It is the SOURCE and not the principal, on purpose: naming the principal would mean
78
+ * unlocking the key before the person has agreed to sign — which, for a password-protected
79
+ * store, means demanding a password in order to show someone what they are being asked to
80
+ * approve. The source is known without touching the key at all.
81
+ *
82
+ * A store key is named by its NAME, whether --key chose it or the default pointer did: the
83
+ * statement says what will sign, and how the name was chosen is not part of what is being
84
+ * approved. The pinned wording is cca's (2026-09-10 20:47Z). */
85
+ export declare function describeKeySource(src: LoginSource): string;
86
+ /** Render seconds the same way in every lane. Written out explicitly so Go and Rust
87
+ * reproduce it exactly — a shared format nobody has to reverse-engineer. */
88
+ export declare function formatDuration(seconds: number): string;
89
+ /** Format a Unix timestamp as YYYY-MM-DDTHH:MM:SSZ, matching the other two lanes. */
90
+ export declare function formatRfc3339Utc(unixSeconds: number): string;
91
+ /** Read a y/N answer. Default is NO: anything that is not an explicit yes refuses,
92
+ * including EOF, so a login cannot be completed by a closed stdin. */
93
+ export declare function confirm(): Promise<boolean>;
94
+ /** Accept the two hex seed-file shapes in use: 64 hex characters (a raw 32-byte seed) and
95
+ * 128 (seed followed by public key), the shape the first consumer's `key` files carry (answer 4). */
96
+ export declare function seedFromHexFile(text: string): Uint8Array;
97
+ /** GET the request. The CLI owns HTTP; the SDK never opens a socket (archon#16). */
98
+ export declare function fetchLoginRequest(audience: string, id: string): Promise<LoginRequest>;
99
+ /** Deliver the answer and report the service's verdict as an error, which is what the
100
+ * confirmed form wants: a refusal ends the command. */
101
+ export declare function postLoginAnswer(audience: string, id: string, answer: LoginAnswer): Promise<void>;
102
+ /** The service's answer to an offer. `page`, when the service has one, is the address the
103
+ * person opens, carrying the code in its fragment. No audience here either — in this form the
104
+ * audience is the prover's own configuration — and a response carrying one is refused. */
105
+ export interface OfferResponse {
106
+ code: string;
107
+ scope: string[];
108
+ valid_for: number;
109
+ expires_in: number;
110
+ interval: number;
111
+ page?: string;
112
+ }
113
+ /** The offers form. The order is §4.1's, rule by rule, and the same before-any-network
114
+ * discipline as the confirmed form: everything decidable without the service — the custody,
115
+ * the authority file, the scope, the validity, the audience — is decided first, so those
116
+ * refusals land before an offer exists. */
117
+ export declare function runOffer(args: string[], write: (text: string) => void, io: LoginIo): Promise<void>;
118
+ /** §4.1 rule 1. The audience is --audience, or ARCHON_AUDIENCE as the configured default,
119
+ * checked exactly the same way: it must be a fixed point of §2.1's grammar — the very check
120
+ * the server applies to its own configuration — and the CLI refuses to start otherwise. The
121
+ * `/login/00` is the shortest invocation URL the grammar admits, there only to make the
122
+ * audience parseable as one; feeding the audience through the scheme's derivation asks the
123
+ * one question that matters: is this the string the service binds? */
124
+ export declare function configuredAudience(flag: string | undefined): string;
125
+ /** The one line about the page address, printed and MARKED, never opened (§4.1 rule 1; ADR
126
+ * 0007 §C.7 (6)). "On the service's own origin" is a byte-exact comparison of scheme and host
127
+ * with the audience's — a differently spelled origin fails closed, the right direction for an
128
+ * address a person is about to click — and launching a browser is the person's action, never
129
+ * this command's: spawning a platform opener by name is the PATH surface §C.5 refuses. */
130
+ export declare function describePage(audience: string, page: string): string;
131
+ /** §4.1 rule 2, done by the prover for itself: the request's scope must be what was offered,
132
+ * entry for entry, in order, and its validity equal. The service refuses a mismatched begin
133
+ * before storing anything — but a prover that relied on that would be trusting the service
134
+ * about the one thing it is about to sign. */
135
+ export declare function checkAgainstOffer(r: LoginRequest, scope: string[], validFor: number): void;
136
+ /** Turn a non-success response into a diagnosis. RFC 8628's error vocabulary is used where
137
+ * the service speaks it, since this protocol adopts that shape. */
138
+ export declare function loginHttpError(status: number, body: string): string;
139
+ /** The possession proof over this request, plus the person's principal as canonical key
140
+ * text. The principal is derived here — a property of the seed, not of the scheme — so
141
+ * only the proof itself waits on sdk/ts/login.
142
+ *
143
+ * LOUD ON PURPOSE until then: a locally computed binding that merely looks right would
144
+ * produce proofs that verify nowhere and take a day to explain. */
145
+ export declare function proveLogin(seed: Uint8Array, audience: string, request: LoginRequest): {
146
+ proof: Uint8Array;
147
+ principal: string;
148
+ };