@brass-build/cli 0.3.0 → 0.4.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.
Files changed (55) hide show
  1. package/AGENTS.md +170 -11
  2. package/CHANGELOG.md +18 -0
  3. package/README.md +76 -14
  4. package/dist/api.d.ts +45 -0
  5. package/dist/api.d.ts.map +1 -1
  6. package/dist/api.js +21 -2
  7. package/dist/api.js.map +1 -1
  8. package/dist/approval-prompt.d.ts +25 -0
  9. package/dist/approval-prompt.d.ts.map +1 -0
  10. package/dist/approval-prompt.js +44 -0
  11. package/dist/approval-prompt.js.map +1 -0
  12. package/dist/args.d.ts.map +1 -1
  13. package/dist/args.js +10 -1
  14. package/dist/args.js.map +1 -1
  15. package/dist/cli.d.ts.map +1 -1
  16. package/dist/cli.js +189 -17
  17. package/dist/cli.js.map +1 -1
  18. package/dist/commands.d.ts +28 -1
  19. package/dist/commands.d.ts.map +1 -1
  20. package/dist/commands.js +358 -24
  21. package/dist/commands.js.map +1 -1
  22. package/dist/login.d.ts +1 -0
  23. package/dist/login.d.ts.map +1 -1
  24. package/dist/login.js +14 -12
  25. package/dist/login.js.map +1 -1
  26. package/dist/project.d.ts +8 -0
  27. package/dist/project.d.ts.map +1 -1
  28. package/dist/project.js +75 -7
  29. package/dist/project.js.map +1 -1
  30. package/dist/sdk-pairing.d.ts +9 -0
  31. package/dist/sdk-pairing.d.ts.map +1 -0
  32. package/dist/sdk-pairing.js +42 -0
  33. package/dist/sdk-pairing.js.map +1 -0
  34. package/dist/session.d.ts +15 -1
  35. package/dist/session.d.ts.map +1 -1
  36. package/dist/session.js +72 -10
  37. package/dist/session.js.map +1 -1
  38. package/dist/store.d.ts +10 -0
  39. package/dist/store.d.ts.map +1 -1
  40. package/dist/store.js +41 -0
  41. package/dist/store.js.map +1 -1
  42. package/dist/version.d.ts +2 -2
  43. package/dist/version.js +1 -1
  44. package/package.json +2 -1
  45. package/src/api.ts +80 -2
  46. package/src/approval-prompt.ts +75 -0
  47. package/src/args.ts +10 -1
  48. package/src/cli.ts +232 -16
  49. package/src/commands.ts +468 -30
  50. package/src/login.ts +24 -11
  51. package/src/project.ts +82 -7
  52. package/src/sdk-pairing.ts +53 -0
  53. package/src/session.ts +100 -8
  54. package/src/store.ts +77 -0
  55. package/src/version.ts +1 -1
package/AGENTS.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Instructions for AI coding agents
2
2
 
3
3
  You are likely an AI coding agent publishing a Brass app you built against
4
- `@brass-build/client`. This tool is how you ship it and how you pull a
5
- schema to build against. The [README](./README.md) is the full reference;
4
+ `@brass-build/client`. This tool is how you ship it, and how you read the
5
+ document you are building against. The [README](./README.md) is the full reference;
6
6
  this file is the short path for you.
7
7
 
8
8
  ## Follow your organization's coding instructions first
@@ -50,8 +50,11 @@ npx @brass-build/cli login --start # prints the approval URL + code
50
50
  npx @brass-build/cli login --check --wait # polls until they approve
51
51
  ```
52
52
 
53
- `--start` prints an approval URL and a short code and exits. Give both to the
54
- human in your next message, then run `--check --wait`. It polls for up to two
53
+ `--start` prints an approval URL and a short code and exits. **Put both in the
54
+ visible text of your next message**, not only in the command output: most
55
+ interfaces collapse tool output, so a link left there reaches nobody and the
56
+ sign-in waits forever. Write the URL and the code out, say what the person has
57
+ to do with them, then run `--check --wait`. It polls for up to two
55
58
  minutes (`--wait <seconds>` for a different bound) and stores the session the
56
59
  moment they approve. A code that lapses is replaced and the new one printed,
57
60
  so the sign-in outlives any single code and a session started early is still
@@ -95,14 +98,16 @@ publish, deploy, or open the live URL). Run it, do what it says, then run it
95
98
  again. The steps below are what it walks you through:
96
99
 
97
100
  1. Build the app to a static bundle (its `brass-app.json` capability
98
- manifest must be in the output).
101
+ manifest must be in the output, at `/.well-known/brass-app.json`).
102
+ Confirm it is there after the build: some bundlers skip dot-directories
103
+ when they copy static assets.
99
104
  2. Make sure a credential is available: `BRASS_SERVICE_TOKEN` in the
100
105
  environment (or `--token`) for CI, or a `brass login` session for local
101
106
  development. When `brass status` reports none, run the sign-in yourself,
102
107
  as [Signing in](#signing-in) describes.
103
108
  Starting it, relaying the URL, and checking it through to approved is your
104
109
  step, not a handoff you stop at. (Or the human mints a service token in
105
- the dashboard: org Settings, then Service tokens.)
110
+ the dashboard: org Settings, then Access tokens.)
106
111
  3. Publish:
107
112
 
108
113
  ```sh
@@ -114,22 +119,141 @@ again. The steps below are what it walks you through:
114
119
  its own organization, so no `--org` is needed. If the pipeline does not
115
120
  persist `.brass/project.json` between runs, set a stable `client_token`
116
121
  (a `"client_token"` in `brass-app.json`, or `--client-token`) so the
117
- first create is idempotent and re-runs resolve the same app.
122
+ first create is idempotent and re-runs resolve the same app. A create
123
+ that carries no `client_token` warns on stderr; act on that warning,
124
+ because the duplicate apps it predicts appear only on later runs.
125
+
126
+ The command reads `<dir>/.well-known/brass-app.json`, then
127
+ `brass-app.json` in the working directory, so a manifest in either place
128
+ is found without `--manifest`.
118
129
 
119
130
  Run with `--json` to get the result (`app_id`, `url`) as JSON on stdout for
120
131
  your own parsing. A non-zero exit means the publish failed, and the reason is
121
132
  on stderr.
122
133
 
134
+ ## Opening the app in a browser, signed in
135
+
136
+ Building the app is not verifying it. What a person will do is open it,
137
+ sign in, and use it, and until you have done that yourself you know only
138
+ that it compiles. `brass browser-session` is how you sign in: it prints a
139
+ URL that opens the app as the human whose machine you are on, so you can
140
+ drive the real thing rather than reporting it verified by types.
141
+
142
+ ```sh
143
+ npx @brass-build/cli browser-session --return-to http://localhost:5173/
144
+ ```
145
+
146
+ That prints one URL on stdout. Open it in the browser you drive, and the
147
+ app boots signed in. The URL is single-use and expires two minutes after
148
+ it is printed, so mint it at the moment you are ready to navigate, not
149
+ ahead of time, and put it straight into the browser: it is a credential
150
+ for as long as it lives, so keep it out of files you commit, PR bodies,
151
+ and anything you print back to the human.
152
+
153
+ `--return-to` is where the browser lands, and it has to be on the app's
154
+ redirect allowlist. A new app allows any `localhost` and `127.0.0.1`
155
+ port, so a dev server needs nothing configured. `--app <appId>` names the
156
+ app, and without it the command reads `.brass/project.json`, so after a
157
+ publish in the same directory you can leave it off.
158
+
159
+ Point it at the published URL to drive what you actually shipped:
160
+
161
+ ```sh
162
+ npx @brass-build/cli browser-session --return-to https://<slug>.onbrass.app/
163
+ ```
164
+
165
+ A published app allows its own URL, and the printed link carries the
166
+ browser through the hosted app's access gate as well as signing it in, so
167
+ one navigation reaches the running app either way.
168
+
169
+ The published URL is also the one to use when the app was first created by
170
+ your CI rather than from a machine someone works on. Such an app carries no
171
+ `localhost` entry, so a handoff aimed at a dev server answers that the
172
+ `return_to` is not on the allowlist. Add the entry yourself to work locally
173
+ (the app's Redirect URLs, in its dashboard page) or point the handoff at
174
+ what CI published.
175
+
176
+ ### You can drive a browser
177
+
178
+ If you have no browser tool to hand, install one rather than concluding
179
+ this cannot be done from where you are: `npm i -D playwright` (then
180
+ `npx playwright install chromium`) or `npm i -D puppeteer` gives you a
181
+ headless Chromium you script from Node, which is all this needs. A
182
+ sandbox with no display still runs headless Chromium. Reaching for a
183
+ `curl` of the page instead does not verify the app: the sign-in and the
184
+ app's own rendering both happen in the browser's JavaScript, so a fetch
185
+ of the HTML shows you a loading shell whatever is wrong underneath.
186
+
187
+ Drive it the way a person would: sign in through the URL, do the thing
188
+ the app is for, and read the result off the screen. Take a screenshot at
189
+ a phone width as well as a desktop one.
190
+
191
+ An app your organization owns needs no approval step: the command mints for
192
+ it directly. That covers the ordinary loop, where `brass publish` creates
193
+ the app after you signed in, and it covers an app somebody else published
194
+ first, from a colleague's machine or from CI.
195
+
196
+ The URL grants no more than your current session: it signs in as the
197
+ same person, in the same apps they have approved. `brass logout` ends
198
+ it along with everything else this machine holds.
199
+
200
+ That is a session for the app, so drive what the app itself renders.
201
+ Brass's own hosted dialogs (the document picker, sharing, version
202
+ history) authenticate from a Brass session the person established in that
203
+ browser by signing in there, which is deliberately more than a machine's
204
+ credential carries: it would reach their whole account. Exercise those in
205
+ a browser you signed in to yourself, and build the app so the paths you
206
+ drive do not depend on one opening.
207
+
208
+ ### When it says the app needs approving
209
+
210
+ Opening an app that belongs to another organization is the one case that
211
+ asks a human first. The command answers `needs_approval` with an
212
+ `approval_url`:
213
+
214
+ ```json
215
+ { "state": "needs_approval", "app_id": "brass_app_...", "approval_url": "https://auth.brass.build/device/approve-app?request=..." }
216
+ ```
217
+
218
+ You cannot approve it. Give the human the `approval_url`, ask them to
219
+ open it and approve, then run the same command again. They have to be
220
+ signed in to Brass as the same account this machine is signed in as: they
221
+ are approving one of their own machines.
222
+
223
+ Re-running the command while you wait hands you the same link, with its
224
+ lifetime refreshed, so nothing you have already relayed stops working and
225
+ there is no second URL to send. `brass status` reports the outstanding
226
+ approval and how long it has left, so you never have to guess whether one
227
+ is still in flight.
228
+
229
+ Do not sign out and back in to attach the app to your session: that
230
+ discards a working credential and still needs the same human approval.
231
+ Relay the URL.
232
+
233
+ When you know that app's id before signing in, and are not signed in yet,
234
+ name it on the sign-in instead and one approval covers the pair:
235
+
236
+ ```sh
237
+ npx @brass-build/cli login --start --app brass_app_...
238
+ ```
239
+
240
+ The approval page then names that app beside the CLI, and
241
+ `brass browser-session` mints for it on the first try.
242
+
123
243
  ## Pulling a schema to build against
124
244
 
125
245
  To interoperate with documents another app or importer produces, do not
126
246
  hand-write the schema. Open one of its documents and pull the real body:
127
247
 
128
248
  ```sh
129
- npx @brass-build/cli schema pull --doc <docId> --out brass-app.json
249
+ npx @brass-build/cli schema pull --doc <docId>
130
250
  ```
131
251
 
132
- This writes the schema verbatim into your manifest. Build your types against
252
+ This writes the schema verbatim into your manifest. Without `--out` it
253
+ merges into an existing one (`brass-app.json`, `.well-known/`,
254
+ `public/.well-known/`, `static/.well-known/`, in that order), so the
255
+ schema lands in the file your bundle serves rather than a second one
256
+ beside it. Build your types against
133
257
  that copy rather than re-approximating it from memory, since a mismatched
134
258
  `required` shape makes the platform read your app as a different shape. This
135
259
  is a development-time step that needs a signed-in session (`brass login`),
@@ -137,13 +261,48 @@ not a service token. When you only have `BRASS_SERVICE_TOKEN`, ask the human
137
261
  to run `brass login` or to copy the schema from the document's dashboard
138
262
  page.
139
263
 
264
+ ## Reading what the document holds
265
+
266
+ The schema is the shape; this is the data. Read it before you write code
267
+ against it, so your field names, types, and the values you branch on come
268
+ from the document rather than from a guess at what the schema's words mean:
269
+
270
+ ```sh
271
+ npx @brass-build/cli contents --doc <docId>
272
+ ```
273
+
274
+ This writes `contents.json`: the whole document, keyed by root container. A
275
+ map root is the object your app reads through `doc.map(root)`, so what is in
276
+ the file is what you will render. `--stdout` pipes it instead.
277
+
278
+ Read the whole file, not the first few records. A file's records are grouped
279
+ by type, so its opening records are a couple of the types it carries and none
280
+ of the rest, and an app built against those breaks on the first record of any
281
+ other type. Work out the full set before you design anything:
282
+
283
+ ```sh
284
+ npx @brass-build/cli contents --doc <docId> --stdout \
285
+ | jq '.instances | map(.type) | group_by(.) | map({type: .[0], count: length})'
286
+ ```
287
+
288
+ Then pull an example of each type you plan to handle and build against those.
289
+ `--stream <name>` reads a stream other than `default`. This needs the same
290
+ signed-in session `schema pull` does.
291
+
292
+ Reading a file Brass is still importing waits for the import to finish, so
293
+ the command runs long on a large one rather than failing. It prints each step
294
+ to stderr; `--no-wait` reads once and fails instead.
295
+
140
296
  ## Verifying
141
297
 
142
298
  `npx @brass-build/cli status` is the check to run before and after a publish:
143
299
  it confirms the credential authenticates and reports whether the app is
144
300
  deployed, with the next step to take. `npx @brass-build/cli whoami` is the
145
- narrower check when you only need to confirm the credential works. After a
146
- publish, open the reported URL to confirm the app loads.
301
+ narrower check when you only need to confirm the credential works.
302
+
303
+ After a publish, open the reported URL and drive the app signed in, as
304
+ [Opening the app in a browser](#opening-the-app-in-a-browser-signed-in)
305
+ describes. That is the check the others stand in for.
147
306
 
148
307
  ## When a command fails
149
308
 
package/CHANGELOG.md CHANGED
@@ -6,6 +6,24 @@ package follows [semantic versioning](https://semver.org/spec/v2.0.0.html).
6
6
  While the version is below `1.0.0`, minor releases may introduce breaking
7
7
  changes.
8
8
 
9
+ ## 0.4.0
10
+
11
+ ### Added
12
+
13
+ - `brass contents --doc <docId>` writes a document out as JSON, so you can
14
+ build and test against the data your app will really see rather than
15
+ against a fixture you wrote by hand. Each root container is a key,
16
+ holding what `doc.map(root)` and `doc.list(root)` return.
17
+ - `brass browser-session --return-to <url>` prints a single-use URL that opens
18
+ your app signed in as you, so a coding agent driving a browser can check its
19
+ work as a signed-in user.
20
+
21
+ ### Changed
22
+
23
+ - `brass publish` and `brass schema pull` look for `brass-app.json` in the
24
+ current directory and the common bundle locations, so neither needs
25
+ `--manifest` or `--out` unless the manifest sits somewhere else.
26
+
9
27
  ## 0.3.0
10
28
 
11
29
  ### Changed
package/README.md CHANGED
@@ -1,12 +1,10 @@
1
1
  # @brass-build/cli
2
2
 
3
3
  From a terminal or a CI pipeline, the `brass` command publishes a Brass
4
- app's built bundle and pulls document schemas. It wraps the same data API the
4
+ app's built bundle and reads the documents you build against. It wraps the same data API the
5
5
  dashboard uses, authenticated by a token instead of a browser session, so
6
6
  the whole publish workflow runs unattended.
7
7
 
8
- This package tracks the platform's `0.2.x` line.
9
-
10
8
  ## Install
11
9
 
12
10
  No install step. Run it with `npx`:
@@ -62,6 +60,21 @@ export BRASS_SERVICE_TOKEN=brass_sk_...
62
60
  npx @brass-build/cli whoami
63
61
  ```
64
62
 
63
+ ## Opening your app signed in
64
+
65
+ `browser-session` prints a single-use URL that opens your app as you, for a
66
+ browser an automated tool is driving:
67
+
68
+ ```sh
69
+ npx @brass-build/cli browser-session --return-to http://localhost:5173/
70
+ ```
71
+
72
+ It exists for coding agents, which have no browser session of their own and
73
+ otherwise cannot check that what they built works for a signed-in user. If you
74
+ are at your own machine, opening the app in your own browser does the same
75
+ thing with fewer steps. `AGENTS.md` in this package documents the flow,
76
+ including what to do when the app has not been approved for this machine yet.
77
+
65
78
  ## Status
66
79
 
67
80
  `status` reports the credential and app state for the target environment and
@@ -99,8 +112,9 @@ For a pipeline that stands the app up from scratch and does not persist
99
112
  `.brass/project.json` between runs, set a stable `client_token` (a
100
113
  `"client_token"` in `brass-app.json`, or `--client-token`). Repeated first
101
114
  publishes then resolve the same app instead of creating a duplicate each run.
102
- A service token creates the app in its own organization, so no `--org` is
103
- needed.
115
+ A create that carries no `client_token` says so on stderr, since the duplicate
116
+ it can produce shows up only later. A service token creates the app in its own
117
+ organization, so no `--org` is needed.
104
118
 
105
119
  The command enables hosting if needed, uploads the bundle, waits for the
106
120
  platform to register the slot, and reports the URL. The URL can answer 404
@@ -109,11 +123,17 @@ misses. The platform reads your app's capabilities
109
123
  (`opens` / `creates` / `schema`) from the `/.well-known/brass-app.json` you
110
124
  serve, so keep that manifest in the bundle.
111
125
 
126
+ Without `--manifest`, the command reads `<dir>/.well-known/brass-app.json`
127
+ and falls back to `brass-app.json` in the working directory, so the manifest
128
+ you ship at `/.well-known/` is found where it already sits. A manifest that is
129
+ present and cannot be parsed fails the publish, naming the file.
130
+
112
131
  Flags: `--app`, `--name`, `--org` (organization to own a newly created app;
113
132
  defaults to a service token's own org), `--client-token` (stable idempotency
114
- key for a first create), `--slug` (preferred subdomain), `--manifest`
115
- (default `brass-app.json`), `--visibility` (`private`, `invitee_visible` or
116
- `public`), `--gate` (`on` or `off`, the hosted load gate).
133
+ key for a first create), `--slug` (preferred subdomain), `--manifest` (a
134
+ manifest path, overriding the search above), `--visibility` (`private`,
135
+ `invitee_visible` or `public`), `--gate` (`on` or `off`, the hosted load
136
+ gate).
117
137
 
118
138
  ## Pull a schema
119
139
 
@@ -121,14 +141,55 @@ To build against a shape another app or importer produces, open one of its
121
141
  documents and copy its schema into your manifest:
122
142
 
123
143
  ```sh
124
- npx @brass-build/cli schema pull --doc <docId> --out brass-app.json
144
+ npx @brass-build/cli schema pull --doc <docId>
125
145
  ```
126
146
 
127
147
  This writes the document's schema body verbatim into the manifest's `schema`
128
148
  field, preserving everything else. That is the same copy-verbatim step the
129
- SDK's schema guide describes, done for you. It is a development-time action
130
- that needs a signed-in session (`brass login`), since a service token cannot
131
- fetch schemas.
149
+ SDK's schema guide describes, done for you.
150
+
151
+ Without `--out` it merges into an existing manifest, checking
152
+ `brass-app.json`, `.well-known/`, `public/.well-known/` and
153
+ `static/.well-known/` in that order, and writes `brass-app.json` when it finds
154
+ none. It never writes into a build output directory, where the next build
155
+ would drop it.
156
+
157
+ Pulling a schema is a development-time action that needs a signed-in session
158
+ (`brass login`), since a service token cannot fetch schemas.
159
+
160
+ ## Read what a document holds
161
+
162
+ A schema says what shape the records take; to get the records themselves,
163
+ write the document out as JSON:
164
+
165
+ ```sh
166
+ npx @brass-build/cli contents --doc <docId>
167
+ ```
168
+
169
+ This writes `contents.json` (`--out <path>` for somewhere else, `--stdout` to
170
+ pipe it). The file is the whole document, keyed by root container: a map root
171
+ is the object your app reads through `doc.map(root)`, a list root its items,
172
+ in the same shapes your code will see.
173
+
174
+ The whole document, not a sample. A file's records are grouped by type, so any
175
+ slice off the front carries a couple of the types it holds and none of the
176
+ rest; with the file on disk you can count the types, pull an example of each,
177
+ or filter to one, and every answer covers everything the document has:
178
+
179
+ ```sh
180
+ npx @brass-build/cli contents --doc <docId> --stdout \
181
+ | jq '.instances | map(.type) | group_by(.) | map({type: .[0], count: length})'
182
+ ```
183
+
184
+ Brass fetches the document the way an app does, as the compact CRDT snapshot
185
+ plus the ops after it, and unpacks it here, so the download stays small
186
+ whatever the file's size. `--stream <name>` reads a stream other than
187
+ `default` and `--branch <id>` a branch other than the default. Like
188
+ `schema pull`, this needs a signed-in session (`brass login`).
189
+
190
+ Reading a file Brass is still importing waits for the import to finish, and
191
+ reports each step it moves through. `--wait <seconds>` moves the deadline
192
+ (900 by default) and `--no-wait` reads once and fails instead.
132
193
 
133
194
  ## Pull your organization's agent instructions
134
195
 
@@ -169,9 +230,10 @@ whenever you pull to any file other than `CLAUDE.md`.
169
230
  ```
170
231
 
171
232
  The service token creates the app in its own organization on the first run.
172
- Give `brass-app.json` a stable `"client_token"` so that first create is
233
+ Give your `brass-app.json` a stable `"client_token"` so that first create is
173
234
  idempotent (repeated runs resolve the same app rather than duplicating it),
174
- or commit `.brass/project.json` to pin the app id.
235
+ or commit `.brass/project.json` to pin the app id. A run with neither creates
236
+ a new app each time, and warns that it did.
175
237
 
176
238
  Add `--json` to any command to emit the machine-readable result on stdout
177
239
  (human status stays on stderr).
package/dist/api.d.ts CHANGED
@@ -42,6 +42,45 @@ export interface DocumentStreams {
42
42
  export interface DocumentTypeSummary {
43
43
  schema_type?: string;
44
44
  }
45
+ export type DocumentJoinSnapshot = {
46
+ kind: 'inline';
47
+ data_b64: string;
48
+ } | {
49
+ kind: 'presigned';
50
+ url: string;
51
+ expires_at: string;
52
+ raw_bytes: number;
53
+ };
54
+ export type DocumentJoinTailOp = {
55
+ seq: number;
56
+ op_blob_b64: string;
57
+ } | {
58
+ seq: number;
59
+ op_blob_url: string;
60
+ op_blob_bytes: number;
61
+ };
62
+ export interface DocumentWorkStatus {
63
+ message: string;
64
+ pending: boolean;
65
+ blocking: boolean;
66
+ progress?: number;
67
+ }
68
+ export interface DocumentJoin {
69
+ doc_id: string;
70
+ branch_id: string;
71
+ stream_branch_id?: string;
72
+ name?: string;
73
+ schema_type?: string;
74
+ snapshot: DocumentJoinSnapshot | null;
75
+ tail_ops: DocumentJoinTailOp[];
76
+ snapshot_seq: number;
77
+ current_seq: number;
78
+ status?: DocumentWorkStatus;
79
+ }
80
+ export interface DocumentDetail {
81
+ doc_id: string;
82
+ status?: DocumentWorkStatus;
83
+ }
45
84
  export interface AgentInstructionsResponse {
46
85
  content: string;
47
86
  updated_at?: string;
@@ -61,6 +100,12 @@ export declare class BrassApiError extends Error {
61
100
  readonly status: number;
62
101
  constructor(status: number, message: string);
63
102
  }
103
+ /**
104
+ * Fetch bytes from a presigned URL. Not an API call: the signature is the
105
+ * credential, so no auth header goes with it, and sending one is refused as
106
+ * a second credential on the request.
107
+ */
108
+ export declare function getPresigned(url: string): Promise<Uint8Array>;
64
109
  /** A failed fetch as the caller should read it, naming a timeout as one. */
65
110
  export declare function networkError(what: string, cause: unknown): BrassApiError;
66
111
  export declare class BrassApi {
package/dist/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
package/dist/api.js CHANGED
@@ -23,6 +23,24 @@ const REQUEST_TIMEOUT_MS = 30_000;
23
23
  // The upload carries the whole bundle, so it is bounded far more loosely than
24
24
  // a request that carries a few hundred bytes.
25
25
  const UPLOAD_TIMEOUT_MS = 300_000;
26
+ /**
27
+ * Fetch bytes from a presigned URL. Not an API call: the signature is the
28
+ * credential, so no auth header goes with it, and sending one is refused as
29
+ * a second credential on the request.
30
+ */
31
+ export async function getPresigned(url) {
32
+ let response;
33
+ try {
34
+ response = await fetch(url, { signal: AbortSignal.timeout(UPLOAD_TIMEOUT_MS) });
35
+ }
36
+ catch (cause) {
37
+ throw networkError('fetching document bytes', cause);
38
+ }
39
+ if (!response.ok) {
40
+ throw new BrassApiError(response.status, `Could not fetch the document's bytes (${response.status}).`);
41
+ }
42
+ return new Uint8Array(await response.arrayBuffer());
43
+ }
26
44
  /** A failed fetch as the caller should read it, naming a timeout as one. */
27
45
  export function networkError(what, cause) {
28
46
  const timedOut = cause instanceof Error &&
@@ -50,8 +68,9 @@ export class BrassApi {
50
68
  async request(method, path, body) {
51
69
  const headers = {
52
70
  ...(await this.auth.headers()),
53
- // Version telemetry; the platform logs it so pinned CI copies
54
- // stay visible in the deployed-version distribution.
71
+ // Names this CLI and its version. Brass answers a build too old to
72
+ // serve with an upgrade message, rather than a failure that names
73
+ // something else.
55
74
  'x-brass-client': CLI_CLIENT_ID,
56
75
  };
57
76
  let init = { method, headers };
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export interface ApprovalPromptInput {
2
+ /** Where the human approves, user code prefilled where the server offers it. */
3
+ url: string;
4
+ /** The code they confirm on that page, for a request that carries one. An
5
+ * app approval names the app on its own page instead, so it has none. */
6
+ code?: string;
7
+ /** What the reader is being asked to approve. Defaults to the device grant,
8
+ * which is what most of these are. */
9
+ heading?: string;
10
+ /** Why this prompt is showing again, when it is not the first time. */
11
+ lead?: string | null;
12
+ /** The command that finishes the sign-in, for a caller that exits before
13
+ * approval. A blocking sign-in polls on its own and passes the line it
14
+ * waits under instead. */
15
+ nextCommand?: string | null;
16
+ /** What a caller with no command to name says under the block. */
17
+ closing?: string | null;
18
+ /** Set by the flow a caller who cannot approve is the usual reason to run
19
+ * (`--start` / `--check`), which adds the note asking an agent to pass the
20
+ * link on. The blocking `brass login` leaves it unset: whoever ran it is
21
+ * waiting to approve. */
22
+ relaying?: boolean;
23
+ }
24
+ export declare function renderApprovalPrompt(input: ApprovalPromptInput): string;
25
+ //# sourceMappingURL=approval-prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-prompt.d.ts","sourceRoot":"","sources":["../src/approval-prompt.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,mBAAmB;IAClC,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ;8EAC0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;2CACuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;+BAE2B;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;8BAG0B;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CA0BvE"}
@@ -0,0 +1,44 @@
1
+ // The one rendering of an approval a human has to give: the URL to open, the
2
+ // code to confirm where there is one, plus what to do next. Every phase of the
3
+ // sign-in prints through here, so a fresh grant, a resumed one, and a renewed
4
+ // one read the same, and so does the app approval `brass browser-session`
5
+ // asks for, which is the same request with a different subject.
6
+ //
7
+ // Whether the reader is the person who approves decides whether the block
8
+ // needs a relay instruction, and the caller narrows it: `brass login` blocks
9
+ // until approval, so whoever ran it is waiting to approve, while `--start` /
10
+ // `--check` exist for a caller that cannot hold a command open, which is
11
+ // usually an agent. Usually, not always, so the note there is addressed to an
12
+ // agent as a condition rather than asserted about the reader, and a person
13
+ // running `--start` themselves reads past it.
14
+ //
15
+ // The caller is what narrows it because `isTTY` answers the wrong question
16
+ // twice: an agent harness that allocates a pty (many do, for colored output)
17
+ // reads as a watched terminal, and `brass login | tee` reads as an agent.
18
+ //
19
+ // The frame is ASCII: this goes to whatever console the caller has, and a
20
+ // box-drawing character that renders as a replacement glyph costs more
21
+ // prominence than the frame buys.
22
+ const RULE = '='.repeat(64);
23
+ export function renderApprovalPrompt(input) {
24
+ const lines = [];
25
+ if (input.lead)
26
+ lines.push(input.lead, '');
27
+ lines.push(RULE, input.heading ?? ' To approve this sign-in, open this link and confirm the code:', '', ` ${input.url}`);
28
+ if (input.code)
29
+ lines.push(` Code: ${input.code}`);
30
+ if (input.relaying === true) {
31
+ lines.push('', input.code
32
+ ? ' If you are an AI agent, put the link and the code directly in your'
33
+ : ' If you are an AI agent, put the link directly in your', ' reply. The person who approves often cannot see this output.');
34
+ }
35
+ lines.push(RULE);
36
+ if (input.nextCommand) {
37
+ lines.push('', `Then run \`${input.nextCommand}\` to finish signing in.`);
38
+ }
39
+ else if (input.closing) {
40
+ lines.push('', input.closing);
41
+ }
42
+ return lines.join('\n');
43
+ }
44
+ //# sourceMappingURL=approval-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-prompt.js","sourceRoot":"","sources":["../src/approval-prompt.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+EAA+E;AAC/E,8EAA8E;AAC9E,0EAA0E;AAC1E,gEAAgE;AAChE,EAAE;AACF,0EAA0E;AAC1E,6EAA6E;AAC7E,6EAA6E;AAC7E,yEAAyE;AACzE,8EAA8E;AAC9E,2EAA2E;AAC3E,8CAA8C;AAC9C,EAAE;AACF,2EAA2E;AAC3E,6EAA6E;AAC7E,0EAA0E;AAC1E,EAAE;AACF,0EAA0E;AAC1E,uEAAuE;AACvE,kCAAkC;AAElC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AA0B5B,MAAM,UAAU,oBAAoB,CAAC,KAA0B;IAC7D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAAK,CAAC,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC3C,KAAK,CAAC,IAAI,CACR,IAAI,EACJ,KAAK,CAAC,OAAO,IAAI,gEAAgE,EACjF,EAAE,EACF,MAAM,KAAK,CAAC,GAAG,EAAE,CAClB,CAAC;IACF,IAAI,KAAK,CAAC,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACtD,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CACR,EAAE,EACF,KAAK,CAAC,IAAI;YACR,CAAC,CAAC,qEAAqE;YACvE,CAAC,CAAC,wDAAwD,EAC5D,+DAA+D,CAChE,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,cAAc,KAAK,CAAC,WAAW,0BAA0B,CAAC,CAAC;IAC5E,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IAGtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAIrC,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAwCD,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAEzD;AA8CD,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAO5E;AAKD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAI9E;AAKD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAMtD;AAcD,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAKrF;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAuC7D;AAID,wBAAgB,UAAU,CACxB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAGpB;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAElE"}
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IAGtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAIrC,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AA4CD,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAEzD;AAmDD,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAO5E;AAKD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAI9E;AAKD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAMtD;AAcD,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAKrF;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAuC7D;AAID,wBAAgB,UAAU,CACxB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAGpB;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAElE"}