@staqon/cli 0.0.0-stage → 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,6 @@
1
+ Copyright (c) 2026 VistarKriya Marketings Private Limited. All rights reserved.
2
+
3
+ This software is proprietary. No licence is granted to copy, modify, merge,
4
+ publish, distribute, sublicense or sell it, except as expressly agreed in
5
+ writing with the copyright holder. It is provided "as is", without warranty of
6
+ any kind.
package/README.md CHANGED
@@ -1,3 +1,232 @@
1
- # Temporary Holding Version
1
+ # @staqon/cli
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Command-line client for the StaqOn partner API. Send messages, post comments, run push-approval
4
+ verifications and broadcast ads as your workspace, from a terminal or a script.
5
+
6
+ - Requires **Node.js 20 or newer**.
7
+ - Talks to `https://staqon.one` by default (override with `--base-url` or `STAQON_BASE_URL`).
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ npm install -g @staqon/cli
13
+ staqon --version
14
+ ```
15
+
16
+ ## Sign in
17
+
18
+ There is no separate `init` step: `staqon login` is the whole setup.
19
+
20
+ ```sh
21
+ staqon login # prints a URL and a one-time code
22
+ staqon login --open # also opens the URL in your browser
23
+ ```
24
+
25
+ 1. The CLI shows a verification URL and a code.
26
+ 2. **The workspace owner** opens the URL and approves the code (they may be asked for their MPIN).
27
+ 3. The CLI polls, receives a session token, and stores it.
28
+
29
+ Where the token lives: the OS keychain when available, otherwise a user-only file
30
+ (`credentials.json` in the `staqon` config directory: `%APPDATA%\staqon` on Windows,
31
+ `$XDG_CONFIG_HOME/staqon` or `~/.config/staqon` elsewhere). The CLI says so when it has to use the file.
32
+
33
+ | Command | What it does |
34
+ |---|---|
35
+ | `staqon whoami` | Workspace, session expiry, rate limits, and which teams can do what |
36
+ | `staqon refresh` | Rotate the session token (the old one works for 5 more minutes) |
37
+ | `staqon logout` | Forget the local token. Revoking it is done by the owner in the web UI |
38
+
39
+ For CI, set `STAQON_TOKEN` instead of logging in (and `STAQON_BASE_URL` if not production). Tokens are
40
+ only ever sent to the host that issued them, and the CLI refuses to send one to a different `--base-url`.
41
+ `refresh` is not available for `STAQON_TOKEN` sessions.
42
+
43
+ ## Teams
44
+
45
+ Most calls are made on behalf of a **team** that holds the right API key. Selection order:
46
+
47
+ 1. `--team <id|slug>` on the command line
48
+ 2. the saved default (`staqon use <team>`; `staqon use` shows it; `staqon use --clear` removes it)
49
+ 3. if the server answers `team_required`:
50
+ - in a terminal, you are asked to pick one (and can save it as the default);
51
+ - otherwise the CLI exits with code 5 and lists the eligible teams. It never picks one for you.
52
+
53
+ `team_not_eligible` (exit 5) means the chosen team has no key for that call; the error lists the teams that do.
54
+ `staqon whoami` shows which teams can send messages and ads.
55
+
56
+ ## Commands
57
+
58
+ Every command accepts the global options below. `--to` takes an email **or** a username and converts it if the
59
+ endpoint wants the other kind (see [Identity](#identity-email-vs-username)).
60
+
61
+ | Global option | |
62
+ |---|---|
63
+ | `--json` | Machine-readable: raw response body on stdout, errors as JSON on stderr |
64
+ | `--team <team>` | Team to act as |
65
+ | `--base-url <url>` | API host |
66
+ | `--verbose` | Print request lines and trace ids to stderr |
67
+ | `--no-color` | Disable colors |
68
+
69
+ ### Messaging
70
+
71
+ ```sh
72
+ staqon message send --email ada@example.com -m "Hello"
73
+ staqon message send --to ada_username -m "Hello" # username resolved to an email
74
+ staqon message send --email ada@example.com --message-file note.txt # or -m - to read stdin
75
+
76
+ staqon messages --username ada_username --limit 20 # read a thread (needs the member's approved link)
77
+ staqon messages --username ada_username --before 152698 # page backwards (--after pages forwards)
78
+
79
+ staqon comment --username ada_username -c "Looks good" --external-ref order-1042
80
+ staqon comment --username ada_username -c "Status" --card @card.json
81
+
82
+ staqon internal message --email ada@example.com -m "FYI" --title "Heads up" --link-url https://example.com
83
+ ```
84
+
85
+ - Message and comment text: up to 60,000 characters. `--external-ref` (max 190) is an idempotency key: a repeat is
86
+ rejected and nothing is posted.
87
+ - `messages --limit` is 1-200 (default 50). Attachment URLs in results are signed and **expire after 1 day**;
88
+ re-fetch the thread for fresh ones.
89
+ - `internal message` sends to a member's one-way API Messages feed and needs their approval.
90
+
91
+ ### Members
92
+
93
+ ```sh
94
+ staqon members list --search "Ada" --limit 50 --page 2
95
+ staqon member ada@example.com # or: staqon member --member-id 311
96
+ staqon internal members --search ada # internal directory (search also matches username)
97
+ ```
98
+
99
+ `members list` shows email and username side by side. `--limit` is **1-100**: the directory is slow server-side
100
+ (about 0.35 s per row) and larger pages hit the gateway timeout. Member searches match **name or email**, not username.
101
+
102
+ ### Verification (push approval)
103
+
104
+ ```sh
105
+ staqon verify start --username ada_username --action "Approve payout #1042" \
106
+ --context "Payout of 5,000 to account ending 1234" --ttl 60
107
+ staqon verify check <verification_id> # prints Verified. / Not verified: <reason>
108
+ staqon verify check <verification_id> --strict # exit 1 unless verified
109
+ staqon verify cancel <verification_id>
110
+ ```
111
+
112
+ - `--ttl` is clamped to 30-180 seconds (default 30). `--action` max 100 chars, `--context` max 500.
113
+ - `check` reasons include `pending`, `declined`, `timeout` and `cancelled`. Without `--strict`, `check` exits 0 for any
114
+ answer; with it, only a verified result exits 0.
115
+ - `cancel` after the member answered returns exit 1 with "Too late to cancel"; after expiry, "already expired".
116
+ - Needs the member's approved link.
117
+
118
+ ### Ads
119
+
120
+ Ads are delivered asynchronously by a background worker.
121
+
122
+ ```sh
123
+ staqon ad image banner.png # upload only; nothing is delivered
124
+ staqon ad create --body-file ad.txt --button-label "Open" --button-url https://example.com --image banner.png --wait
125
+ staqon ad status <ad_request_id> # or --external-ref <ref>
126
+ ```
127
+
128
+ - Images: JPEG, PNG or WebP (checked on file contents), **max 300 KB**; the server crops to 16:9 and downsizes to
129
+ at most 1280x720, so the stored size differs from your file.
130
+ - `ad create`: body 50-900 characters; success is HTTP 202 plus an `ad_request_id`. `--wait` polls every 5 s for up
131
+ to 10 minutes. `--external-ref` (max 150) is an idempotency key.
132
+
133
+ ### Raw access
134
+
135
+ ```sh
136
+ staqon api external/members -q search=ada -q limit=10
137
+ staqon api external/message -d '{"email":"ada@example.com","message":"Hi"}'
138
+ ```
139
+
140
+ Calls any CLI-proxy endpoint directly: `external/{message,messages,comment,members,member,ad,ad-image,ad-status,
141
+ staqon-verify-start,staqon-verify-check,staqon-verify-cancel}` and `internal/{message,members}`.
142
+ `-d` takes inline JSON, `@file.json` or `-` for stdin; `-F k=v` / `-F k=@path` sends multipart.
143
+
144
+ ### Cards
145
+
146
+ `--card` (comment, internal message, verify start) takes a JSON object, inline, `@file.json` or `-`. The CLI
147
+ validates it before sending: required `header_color` (one of the palette colors), `title` (200) and `body` (2000);
148
+ optional `meta_title`, `sub_body`, `icon`, `button` (`label`, `url`; not allowed on verification cards) and `table`
149
+ (2-6 columns, 1-500 rows). Unknown keys are rejected.
150
+
151
+ ## Identity: email vs. username
152
+
153
+ The endpoints disagree: `message send` wants an email, while `messages`, `comment`, `verify` want a username. Give
154
+ `--email`, `--username` or `--to <either>`; the CLI converts when needed.
155
+
156
+ - email -> username is one fast lookup.
157
+ - username -> email tries the directory search, then looks up the member's name via their thread and searches by
158
+ name (fast, but only for members linked to your workspace), then **pages through the whole directory**. That last
159
+ step can take minutes on a large workspace. **If you know the email, pass `--email`.**
160
+
161
+ ## The consent model (why some calls return 403)
162
+
163
+ Members control what a workspace may do. For `messages`, `comment`, `verify *` and `internal message`, the member must
164
+ have approved the link with your workspace in their app. If they have not, the server answers 403 and the CLI prints
165
+ a friendly message and exits with **code 6**:
166
+
167
+ ```
168
+ Error: This member hasn't approved linking with this workspace.
169
+ trace id: ...
170
+ Server said: No approved link for this member
171
+ The member has to approve the link in their app; the CLI can't do it for them.
172
+ ```
173
+
174
+ The CLI can't work around it. Ask the member to approve, then retry. A 403 that is *not* about consent (CLI access
175
+ switched off, workspace inactive) exits with code 3 instead.
176
+
177
+ ## Exit codes
178
+
179
+ | Code | Meaning |
180
+ |---|---|
181
+ | 0 | Success |
182
+ | 1 | General failure: server rejected the request (4xx/5xx), network error or timeout, `verify check --strict` not verified, cancel too late or expired |
183
+ | 2 | Usage error: bad flags or input, caught before anything is sent; also a token used against a different host |
184
+ | 3 | Authentication: not logged in, session expired/revoked (401), or access denied (non-consent 403) |
185
+ | 4 | Rate limited (429): session 30/min, 3,000/day, or the API key's own ceiling. `Retry after` is shown when sent |
186
+ | 5 | Team or key problem: `team_required` (non-interactive), `team_not_eligible`, `no_key` |
187
+ | 6 | Member has not approved the link (consent 403) |
188
+ | 130 | Interrupted (Ctrl-C) |
189
+
190
+ The CLI never retries on its own, except re-asking once after you pick a team interactively.
191
+ Requests time out after 30 s (120 s for member directory listings); override with `STAQON_TIMEOUT_MS`.
192
+
193
+ ## `--json`
194
+
195
+ With `--json`, success prints the server's response body, unchanged, on stdout. Errors print **one JSON object on
196
+ stderr** and nothing on stdout:
197
+
198
+ ```json
199
+ {
200
+ "error": "This member hasn't approved linking with this workspace.",
201
+ "exit_code": 6,
202
+ "status": 403,
203
+ "trace_id": "30becdb4-daac-46b0-9fb6-395249329632",
204
+ "body": { "ok": false, "error": "No approved link for this member" },
205
+ "hint": "Server said: No approved link for this member\n..."
206
+ }
207
+ ```
208
+
209
+ `status`, `trace_id` and `body` appear for errors that came from the server; client-side errors have only
210
+ `error`, `exit_code` and optionally `hint`. In `--json` mode the CLI never prompts, so team selection must be
211
+ explicit (`--team` or a saved default). Tokens are redacted (`stq_cli_***`) from all output. Quote the `trace_id`
212
+ when contacting support.
213
+
214
+ ## Environment variables
215
+
216
+ | Variable | Purpose |
217
+ |---|---|
218
+ | `STAQON_TOKEN` | Use this session token instead of the stored login |
219
+ | `STAQON_BASE_URL` | API host (default `https://staqon.one`) |
220
+ | `STAQON_TIMEOUT_MS` | Request timeout in milliseconds |
221
+
222
+ ## Development
223
+
224
+ ```sh
225
+ npm install
226
+ npm run build # bundle to dist/
227
+ npm test # 52 mocked tests; no network, no login needed
228
+ npm run test:live # optional; needs a login: STAQON_LIVE_USERNAME=... STAQON_LIVE_EMAIL=... (slow case: SLOW=1)
229
+ ```
230
+
231
+ The mocked tests run the real CLI against a local fake server with an isolated config directory, so they never touch
232
+ your real login or keychain.
package/bin/staqon.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/cli.js';