@theplato/tiro-cli 0.4.0 → 0.4.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.
package/AGENTS.md CHANGED
@@ -89,26 +89,15 @@ Two ways to authenticate:
89
89
  The CLI never prints tokens to stdout. `tiro auth status` shows only the
90
90
  first 4 characters of the access token.
91
91
 
92
- ## Security regression suite (pre-deploy contract)
93
-
94
- Every release MUST keep `npm run test:security` green. The suite pins the
95
- following defenses; if any test breaks, the corresponding attack surface
96
- has reopened do not publish.
97
-
98
- | ID | Surface | What the test guards |
99
- |---|---|---|
100
- | **C1** | `lib/config.ts` `validateHostname` | Rejects non-https/non-loopback hostnames so `TIRO_HOSTNAME` / `--hostname` cannot redirect OAuth + API traffic to an attacker. |
101
- | **H1** | `lib/auth/pkce.ts` `verifyState` | Constant-time OAuth state CSRF compare. |
102
- | **H2** | `lib/auth/loopback.ts` | OAuth redirect listener is GET-only, single-shot, `Connection: close` — local processes can't race or replay a callback. |
103
- | **H3** | `lib/api/client.ts` `buildApiUrl` | API path must be relative to the configured hostname refuses absolute / protocol-relative input that would leak the bearer token. |
104
- | **H4** | `lib/config.ts` `getOauthClientId` | DCR `client_id` cache is bound to the hostname it was registered against; a swapped hostname misses the cache. |
105
- | **M1** | `lib/output/file.ts` `assertSafeOutputPath` | `--output` rejects `..` segments unless `--force`; an agent forwarding untrusted input cannot escape its scope. |
106
- | **M2** | `lib/auth/token.ts` `decodeJwtPayload` | Documented as display-only — claims must never gate auth, scope, identity, or expiry decisions. |
107
-
108
- Pre-deploy checklist:
109
-
110
- 1. `npm run typecheck`
111
- 2. `npm run test:security` (regression gate)
112
- 3. `npm test` (full suite)
113
- 4. `npm run build`
114
- 5. Smoke: `node dist/bin/tiro.js auth status`
92
+ ## Security posture (summary)
93
+
94
+ - OAuth uses Authorization Code + PKCE with a CSRF-checked loopback
95
+ redirect. Tokens are held in the OS keychain or `TIRO_TOKEN` only —
96
+ never written to stdout, stderr, or disk in any other form.
97
+ - `TIRO_HOSTNAME` / `--hostname` are validated against an `https://` (or
98
+ loopback) allowlist before any OAuth or API request runs.
99
+ - `--output` paths that escape the working tree require `--force`.
100
+ - A dedicated regression suite (`npm run test:security`) pins these
101
+ surfaces and runs in `prepublishOnly` a broken defense blocks publish.
102
+
103
+ Always run on the latest released version; older versions are deprecated.
package/README.md CHANGED
@@ -108,7 +108,7 @@ tiro notes list
108
108
  ```bash
109
109
  tiro notes list # pretty table in TTY
110
110
  tiro notes list --json # NDJSON for pipes
111
- tiro notes list --keyword "OKR" --since 30d # OpenSearch reorder by keyword
111
+ tiro notes list --keyword "OKR" --since 30d # Reorder by keyword relevance
112
112
  tiro notes list --folder <id> --limit 100 --cursor <token>
113
113
  ```
114
114
 
@@ -287,7 +287,7 @@ The CLI sits on the public Tiro API alongside the MCP server, sharing the same O
287
287
 
288
288
  ```
289
289
  ┌──────────────────────────────┐
290
- │ Tiro Backend (Kotlin)
290
+ │ Tiro Backend
291
291
  │ /v1/external/* + /v1/mcp/* │
292
292
  └──────────────┬────────────────┘
293
293
 
package/dist/bin/tiro.js CHANGED
@@ -1198,17 +1198,18 @@ Examples:
1198
1198
  tiro notes list --folder <id> --limit 50
1199
1199
 
1200
1200
  Keyword matching:
1201
- --keyword reorders results by OpenSearch relevance (case-insensitive,
1202
- full-text against note title and paragraph content). When --keyword is
1203
- set, nextCursor is always null. Without --keyword, results are ordered
1204
- by createdAt desc.
1201
+ --keyword reorders results by full-text relevance over title and
1202
+ paragraph content (case-insensitive), with createdAt desc as tiebreaker
1203
+ when scores are close. When --keyword is set, nextCursor is always null.
1204
+ Without --keyword, results are ordered by recording time desc (falls back
1205
+ to createdAt for memo-only notes).
1205
1206
 
1206
1207
  Note: placeholder notes (title='Untitled' or sourceType='onboarding') are
1207
1208
  filtered out by default. A page of N may return fewer than N visible notes \u2014
1208
1209
  keep paginating to fetch more, or pass --include-untitled to surface them.
1209
1210
  `;
1210
1211
  function registerNotesList(parent) {
1211
- parent.command("list").description("List notes (lightweight metadata).").option("--keyword <text>", 'Reorder by OpenSearch relevance for this keyword (e.g. "OKR")').option("--folder <id>", "Restrict to a folder and its descendants").option(
1212
+ parent.command("list").description("List notes (lightweight metadata).").option("--keyword <text>", 'Reorder by full-text relevance for this keyword (e.g. "OKR")').option("--folder <id>", "Restrict to a folder and its descendants").option(
1212
1213
  "--since <date>",
1213
1214
  "Inclusive lower bound on createdAt (ISO-8601 or relative: 7d, 24h, 30m)"
1214
1215
  ).option("--until <date>", "Exclusive upper bound on createdAt").option(
@@ -1307,12 +1308,16 @@ Examples:
1307
1308
  tiro notes search "release" --since 2026-04-01 --until 2026-05-01
1308
1309
 
1309
1310
  Keyword matching:
1310
- Full-text against note title + paragraph content via OpenSearch.
1311
- Case-insensitive. Multi-word keywords are tokenized \u2014 "OKR planning"
1312
- matches notes containing both terms. The deep search variant (this
1313
- command) hydrates each result with its primary documents (one-pager,
1314
- custom) so an MCP/LLM client can read content alongside metadata in
1315
- one call.
1311
+ Full-text search against note title + paragraph content. Case-insensitive.
1312
+ Multi-word keywords are tokenized \u2014 "OKR planning" matches notes containing
1313
+ both terms. The deep search variant (this command) hydrates each result
1314
+ with its primary documents (one-pager, custom) so an MCP/LLM client can
1315
+ read content alongside metadata in one call.
1316
+
1317
+ Ordering:
1318
+ Results are sorted by full-text relevance, then createdAt desc as
1319
+ tiebreaker. Without --limit, the server returns 50 results (capped
1320
+ at 200). Pass --limit to override.
1316
1321
 
1317
1322
  Note: placeholder notes (title='Untitled' or sourceType='onboarding') are
1318
1323
  filtered out by default. Pass --include-untitled to surface them.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theplato/tiro-cli",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Tiro AI notes & transcripts — agent-first command line",
5
5
  "type": "module",
6
6
  "bin": {