hikoutei 0.5.14 → 0.5.16

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 (50) hide show
  1. package/README.ja.md +35 -4
  2. package/README.ko.md +33 -4
  3. package/README.md +99 -10
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +69 -5
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/checkpoint.d.ts +716 -0
  8. package/dist/cli/checkpoint.d.ts.map +1 -0
  9. package/dist/cli/checkpoint.js +1463 -0
  10. package/dist/cli/checkpoint.js.map +1 -0
  11. package/dist/cli/errors.d.ts +25 -1
  12. package/dist/cli/errors.d.ts.map +1 -1
  13. package/dist/cli/errors.js +25 -1
  14. package/dist/cli/errors.js.map +1 -1
  15. package/dist/cli/flowResult.d.ts +55 -0
  16. package/dist/cli/flowResult.d.ts.map +1 -0
  17. package/dist/cli/flowResult.js +48 -0
  18. package/dist/cli/flowResult.js.map +1 -0
  19. package/dist/cli/gcloudRunner.d.ts +25 -1
  20. package/dist/cli/gcloudRunner.d.ts.map +1 -1
  21. package/dist/cli/gcloudRunner.js +32 -2
  22. package/dist/cli/gcloudRunner.js.map +1 -1
  23. package/dist/cli/humanAuth.d.ts +101 -0
  24. package/dist/cli/humanAuth.d.ts.map +1 -0
  25. package/dist/cli/humanAuth.js +175 -0
  26. package/dist/cli/humanAuth.js.map +1 -0
  27. package/dist/cli/keyProvision.d.ts +327 -0
  28. package/dist/cli/keyProvision.d.ts.map +1 -0
  29. package/dist/cli/keyProvision.js +1204 -0
  30. package/dist/cli/keyProvision.js.map +1 -0
  31. package/dist/cli/saVerify.d.ts +106 -0
  32. package/dist/cli/saVerify.d.ts.map +1 -0
  33. package/dist/cli/saVerify.js +137 -0
  34. package/dist/cli/saVerify.js.map +1 -0
  35. package/dist/cli/sdkError.d.ts +33 -0
  36. package/dist/cli/sdkError.d.ts.map +1 -0
  37. package/dist/cli/sdkError.js +78 -0
  38. package/dist/cli/sdkError.js.map +1 -0
  39. package/dist/cli/setup.d.ts +1 -1
  40. package/dist/cli/setup.js +37 -8
  41. package/dist/cli/setup.js.map +1 -1
  42. package/dist/cli/setupFlow.d.ts +220 -47
  43. package/dist/cli/setupFlow.d.ts.map +1 -1
  44. package/dist/cli/setupFlow.js +1471 -174
  45. package/dist/cli/setupFlow.js.map +1 -1
  46. package/dist/cli/sheetsFactory.d.ts +356 -29
  47. package/dist/cli/sheetsFactory.d.ts.map +1 -1
  48. package/dist/cli/sheetsFactory.js +488 -46
  49. package/dist/cli/sheetsFactory.js.map +1 -1
  50. package/package.json +2 -1
package/README.ja.md CHANGED
@@ -206,15 +206,46 @@ MikroORM は実装の詳細であり、Hikoutei の公開エンティティ API
206
206
 
207
207
  ## プロジェクトステータス
208
208
 
209
- Hikoutei は活発に開発中です。エンティティ API は利用可能ですが、シート編集の
210
- 取り込みと競合表示はまだ発展途上です。マイナーバージョンのアップグレード前に
211
- リリースノートを確認してください。
209
+ Hikoutei は活発に開発中です。現在の EntityManager は、スカラーエンティティの
210
+ ライフサイクル操作、等価条件を使う `find()` / `findOne()`、`find()` の
211
+ `limit` / `offset` ページネーション、コールバック形式の `transactional()` を
212
+ サポートします。通常の読み取り元は常に SQLite であり、Google Sheets では
213
+ ありません。
214
+ シート編集の取り込みと競合表示はまだ発展途上です。マイナーバージョンの
215
+ アップグレード前にリリースノートを確認してください。
212
216
 
213
217
  ## ロードマップ
214
218
 
219
+ EntityManager のロードマップは、以下の実装順序に従います。段階の順序は確定
220
+ していますが、日付やリリース番号は約束しません。
221
+
222
+ 1. **豊富なローカル読み取り**
223
+ - Hikoutei 独自の型付きクエリ契約に、明示的な `eq`、`ne`、`gt`、
224
+ `gte`、`lt`、`lte`、`in`、`nin`、`like` 条件と `orderBy`、
225
+ `count()`、`findAndCount()` を追加します。
226
+ - MikroORM のクエリ型を公開せず、これらを既存の `limit` / `offset`
227
+ ページネーションと組み合わせます。
228
+ 2. **ライフサイクル安全な書き込み**
229
+ - `upsert` と direct/bulk mutation 機能は、エンティティテーブル、
230
+ canonical state、永続的な Sheet effect outbox を 1 つの SQLite
231
+ トランザクションで処理する Hikoutei 独自の契約を通じてのみ追加します。
232
+ - この原子的なライフサイクルを迂回し得る、生の `nativeInsert`、
233
+ `nativeUpdate`、`nativeDelete`、または SQL パススルー API は約束しません。
234
+ 3. **リレーションとロード**
235
+ - many-to-one、one-to-many、`populate()` 機能を追加します。
236
+ - 公開前に、リレーションの SQLite マッピング、Sheets プロジェクション
237
+ 表現、スキーマ動作、競合セマンティクスを一体として設計します。
238
+ 4. **スキーマ運用**
239
+ - マイグレーションとスキーマドリフト管理を追加します。
240
+ - 検証と運用フローを既存のセットアップツールと統合します。
241
+
242
+ ### 同期と運用
243
+
244
+ 以下の作業は EntityManager の各段階と並行して進めます。
245
+
215
246
  - Google Sheets からの意図的なユーザー編集の取り込みを完了する
216
247
  - 更新・削除の競合処理と表示を改善する
217
- - レジストリと直接 provider デプロイのセットアップツールを追加する
248
+ - レジストリと direct-provider デプロイのセットアップツールを改善する
218
249
 
219
250
  現在の作業は[オープンな Issues](https://github.com/ManddarinShop/Hikoutei/issues)を
220
251
  参照してください。
package/README.ko.md CHANGED
@@ -201,15 +201,44 @@ MikroORM은 구현 세부 사항이며 Hikoutei의 공개 엔티티 API에는
201
201
 
202
202
  ## 프로젝트 상태
203
203
 
204
- Hikoutei는 활발히 개발 중입니다. 엔티티 API사용 가능하지만, 시트 편집
205
- 수집과 충돌 표시는 아직 발전 중입니다. 마이너 버전 업그레이드 전에 릴리스
206
- 노트를 확인하세요.
204
+ Hikoutei는 활발히 개발 중입니다. 현재 EntityManager스칼라 엔티티의 생명주기
205
+ 작업, 동등 조건을 사용하는 `find()` / `findOne()`, `find()`의 `limit` /
206
+ `offset` 페이지네이션, 콜백형 `transactional()`을 지원합니다. 일반 읽기는
207
+ Google Sheets가 아니라 항상 SQLite에서 수행됩니다. 시트 편집 수집과 충돌 표시는
208
+ 아직 발전 중입니다. 마이너 버전 업그레이드 전에 릴리스 노트를 확인하세요.
207
209
 
208
210
  ## 로드맵
209
211
 
212
+ EntityManager 로드맵은 아래 구현 순서를 따릅니다. 단계 순서는 확정되어 있지만,
213
+ 일정이나 릴리스 번호는 약속하지 않습니다.
214
+
215
+ 1. **풍부한 로컬 읽기**
216
+ - Hikoutei가 정의한 타입 쿼리 계약에 명시적 `eq`, `ne`, `gt`, `gte`,
217
+ `lt`, `lte`, `in`, `nin`, `like` 조건과 `orderBy`, `count()`,
218
+ `findAndCount()`를 추가합니다.
219
+ - MikroORM 쿼리 타입을 노출하지 않고 이 기능들을 기존 `limit` / `offset`
220
+ 페이지네이션과 조합합니다.
221
+ 2. **생명주기 안전 쓰기**
222
+ - `upsert`와 direct/bulk mutation 기능은 엔티티 테이블, canonical state,
223
+ 내구성 있는 Sheet effect outbox를 하나의 SQLite 트랜잭션에서 처리하는
224
+ Hikoutei 정의 계약을 통해서만 추가합니다.
225
+ - 이 원자적 생명주기를 우회할 수 있는 원시 `nativeInsert`, `nativeUpdate`,
226
+ `nativeDelete` 또는 SQL 패스스루 API는 약속하지 않습니다.
227
+ 3. **관계와 로딩**
228
+ - many-to-one, one-to-many, `populate()` 기능을 추가합니다.
229
+ - 공개 전에 관계의 SQLite 매핑, Sheets 프로젝션 표현, 스키마 동작, 충돌
230
+ 의미론을 함께 설계합니다.
231
+ 4. **스키마 운영**
232
+ - 마이그레이션과 스키마 드리프트 관리를 추가합니다.
233
+ - 검증 및 운영 흐름을 기존 설정 도구와 통합합니다.
234
+
235
+ ### 동기화 및 운영
236
+
237
+ 다음 작업은 EntityManager 단계와 병행합니다.
238
+
210
239
  - Google Sheets에서 의도적인 사용자 편집 수집 완성
211
240
  - 업데이트·삭제 충돌 처리와 표시 개선
212
- - 레지스트리 및 직접 provider 배포를 위한 설정 도구 추가
241
+ - 레지스트리 및 direct-provider 배포를 위한 설정 도구 개선
213
242
 
214
243
  현재 작업은 [오픈 이슈](https://github.com/ManddarinShop/Hikoutei/issues)를
215
244
  참고하세요.
package/README.md CHANGED
@@ -125,11 +125,64 @@ an operation for each write. The sync runtime uses one Google Sheets API
125
125
  provider (the internal `googleSheetsApi` bootstrap option) with a service
126
126
  account — no Apps Script deployment.
127
127
 
128
- **Fastest path:** install the gcloud CLI, run `gcloud auth login`, then
129
- `npx hikoutei setup` — it creates the project, service account, key, and a
130
- spreadsheet owned by that service account, and writes
131
- `GOOGLE_APPLICATION_CREDENTIALS` plus `HIKOUTEI_SYNC_SPREADSHEET_URL` into
132
- your `.env`. The manual steps below remain available for advanced setups.
128
+ **Fastest path:** install the gcloud CLI and log in once with Drive access
129
+ (`gcloud auth login --enable-gdrive-access`), then `npx hikoutei setup` — it
130
+ creates the project, service account, and key, creates a spreadsheet owned
131
+ by your account, shares it with the service account as an Editor, verifies
132
+ service-account access, and writes `GOOGLE_APPLICATION_CREDENTIALS` plus
133
+ `HIKOUTEI_SYNC_SPREADSHEET_URL` into your `.env`. The human access token is
134
+ used in memory only and never stored. Automatic setup runs on macOS and
135
+ Linux; on Windows a non-dry-run is refused before any mutation and manual
136
+ setup is available. Interrupted runs resume from a local checkpoint
137
+ (`.hikoutei-setup-state.json`); a spreadsheet create whose outcome is
138
+ unknown is reconciled by its creation marker on the next run and setup
139
+ never creates a second spreadsheet (inspect Drive and rerun if setup
140
+ reports `sheet_create_uncertain`, and a create rejected up front with
141
+ HTTP 400/403 plus a confirmed-zero marker lookup rolls back to `key_ready`
142
+ so a corrected rerun starts a fresh marker). Sharing is write-ahead too:
143
+ `spreadsheet_share_started` is persisted before the idempotent SA writer
144
+ permission ensure and `spreadsheet_shared` after it, so a crash between
145
+ the remote permission mutation and the checkpoint write resumes the
146
+ ensure on the next run and never creates a second spreadsheet. The
147
+ service-account key is
148
+ created under a write-ahead contract too: the user-managed key list is
149
+ recorded as a baseline before the single gcloud key create, and
150
+ `key_create_started`/`key_ready` checkpoints let a crashed run recover a
151
+ staged or installed key instead of creating a second one. Only the
152
+ invocation that just persisted `key_create_started` may issue the one key
153
+ create; resumed runs are reconcile-only and, when no credential and no
154
+ post-baseline key are visible, poll the key list plus staged/final
155
+ evidence for up to two minutes (2, 4, 8, 16, 30, 30, 30 s) before failing
156
+ with `key_create_uncertain` — the create is never retried automatically.
157
+ An unmatched user-managed key with no local credential is never deleted
158
+ automatically — setup fails with `key_create_uncertain` and you inspect
159
+ the key list in the Google Cloud console before rerunning (a
160
+ verified-absent state requires removing the setup state file to reset the
161
+ key checkpoint); reused keys are enforced to owner-only mode 600. An exclusive lock directory
162
+ (`.hikoutei-setup-state.json.lock`) prevents concurrent runs and is never
163
+ removed automatically: a crash leaves an empty lock directory behind, and
164
+ removing it manually is required only when you are certain no setup is
165
+ running. Starting fresh requires removing or moving both the checkpoint and
166
+ the key file, or passing `--project` to recover an existing key —
167
+ checkpointed or identity-matched cloud resources are reused, and setup
168
+ never deletes cloud resources. The manual steps below remain available for
169
+ advanced setups.
170
+
171
+ **Keep setup artifacts out of Git.** `hikoutei setup` writes its defaults
172
+ into the current directory: the service-account key
173
+ (`hikoutei-service-account.json`, owner-only mode 600 — a secret), the
174
+ resume checkpoint (`.hikoutei-setup-state.json` and its `.tmp`/unique-temp
175
+ and `.lock` siblings), private key staging/cleanup directories
176
+ (`.hikoutei-key-stage-*`, `.hikoutei-key-cleanup-*`), and
177
+ `.hikoutei-env-*` temporary env writes. The repository's `.gitignore`
178
+ already ignores these defaults, so a plain `git add .` does not pick them
179
+ up. A `.gitignore` is **not a security boundary**, though: it only keeps
180
+ untracked files out of `git add`, and it does not protect files that are
181
+ already tracked (remove a mistakenly tracked key from history and rotate
182
+ it — delete the user-managed key in the Cloud console and rerun setup).
183
+ When you use a custom `--output` or keep the key or checkpoint at custom
184
+ paths, add those exact paths to your application's ignore rules and never
185
+ commit them.
133
186
 
134
187
  ### Env-driven sync auto-start
135
188
 
@@ -161,7 +214,11 @@ shared on the spreadsheet (the error tells you which email to share).
161
214
  access is not enough.
162
215
  2. **Keep the key server-side.** Put the service-account key path in
163
216
  `GOOGLE_APPLICATION_CREDENTIALS` on the server and the spreadsheet ID in an
164
- untracked secret store. Never put the key in browser code or Git.
217
+ untracked secret store. Never put the key in browser code or Git: add the
218
+ key path (and any custom `.env`/checkpoint paths) to the application's
219
+ `.gitignore` — the defaults created by `hikoutei setup` are already
220
+ ignored, but a `.gitignore` is not a security boundary and does not
221
+ protect already-tracked files.
165
222
  3. **Start the internal sync bootstrap** with `googleSheetsApi` configured. It
166
223
  creates and verifies headers on the registered tabs, then starts outbox
167
224
  delivery and User_Input polling.
@@ -212,15 +269,47 @@ entity API.
212
269
 
213
270
  ## Project status
214
271
 
215
- Hikoutei is in active development. The entity API is usable, while Sheet edit
216
- ingestion and conflict presentation are still evolving. Review release notes
217
- before upgrading minor versions.
272
+ Hikoutei is in active development. The current EntityManager supports scalar
273
+ entity lifecycle operations, equality-filtered `find()` / `findOne()`,
274
+ `limit` / `offset` pagination on `find()`, and callback-style
275
+ `transactional()` work.
276
+ Normal reads always come from SQLite, never Google Sheets. Sheet edit ingestion
277
+ and conflict presentation are still evolving. Review release notes before
278
+ upgrading minor versions.
218
279
 
219
280
  ## Roadmap
220
281
 
282
+ The EntityManager roadmap follows the implementation order below. The sequence
283
+ is committed, but no milestone is tied to a date or release number.
284
+
285
+ 1. **Rich local reads**
286
+ - Add a Hikoutei-owned typed query contract for explicit `eq`, `ne`, `gt`,
287
+ `gte`, `lt`, `lte`, `in`, `nin`, and `like` conditions, plus `orderBy`,
288
+ `count()`, and `findAndCount()`.
289
+ - Compose these capabilities with the existing `limit` / `offset`
290
+ pagination without exposing MikroORM query types.
291
+ 2. **Lifecycle-safe writes**
292
+ - Add `upsert` and direct/bulk mutation capabilities only through a
293
+ Hikoutei-owned contract that preserves one SQLite transaction across the
294
+ entity table, canonical state, and durable Sheet effect outbox.
295
+ - Do not promise raw `nativeInsert`, `nativeUpdate`, `nativeDelete`, or SQL
296
+ pass-through APIs that could bypass that atomic lifecycle.
297
+ 3. **Relationships and loading**
298
+ - Add many-to-one, one-to-many, and `populate()` capabilities.
299
+ - Design SQLite relationship mapping, Sheets projection representation,
300
+ schema behavior, and conflict semantics together before public release.
301
+ 4. **Schema operations**
302
+ - Add migration and schema drift management.
303
+ - Integrate validation and operational workflows with the existing setup
304
+ tooling.
305
+
306
+ ### Synchronization and operations
307
+
308
+ The following work continues in parallel with the EntityManager milestones:
309
+
221
310
  - Complete ingestion of intentional user edits from Google Sheets.
222
311
  - Improve update/delete conflict handling and presentation.
223
- - Add setup tooling for registry and direct provider deployment.
312
+ - Improve setup tooling for registry and direct-provider deployment.
224
313
 
225
314
  See the [open issues](https://github.com/ManddarinShop/Hikoutei/issues)
226
315
  for current work.
@@ -1 +1 @@
1
- {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAmC,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEjF,kEAAkE;AAClE,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,SAAS,CAAC;AAE/C,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,gDAAgD;AAChD,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC;AAanE,eAAO,MAAM,eAAe,QAyBhB,CAAC;AAUb;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,oBAAoB,CA6E5E"}
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAmC,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEjF,kEAAkE;AAClE,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,SAAS,CAAC;AAE/C,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,gDAAgD;AAChD,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC;AAanE,eAAO,MAAM,eAAe,QAkEhB,CAAC;AAUb;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,oBAAoB,CAyG5E"}
package/dist/cli/args.js CHANGED
@@ -5,6 +5,7 @@
5
5
  * the filesystem, or the network. The result is an explicit union so the CLI
6
6
  * entry can branch on help / valid / invalid without inspecting message text.
7
7
  */
8
+ import { isValidGcpProjectId, isValidServiceAccountName } from "./checkpoint.js";
8
9
  import { SETUP_ERROR_CODES, setupFailure } from "./errors.js";
9
10
  /** Default service-account name when `--sa-name` is not given. */
10
11
  export const DEFAULT_SA_NAME = "hikoutei-sa";
@@ -22,10 +23,12 @@ const SETUP_FLAGS = {
22
23
  };
23
24
  export const SETUP_HELP_TEXT = [
24
25
  "hikoutei setup - bootstrap a Google Cloud project, service account, key, and",
25
- "spreadsheet for Hikoutei sync, then write a ready-to-use .env file.",
26
+ "a human-owned spreadsheet for Hikoutei sync, then write a ready-to-use .env file.",
26
27
  "",
27
- "Prerequisites: the gcloud CLI is installed and `gcloud auth login` has been",
28
- "run once (an active account is required).",
28
+ "Prerequisites: the gcloud CLI is installed and `gcloud auth login",
29
+ "--enable-gdrive-access` has been run once. Setup creates the spreadsheet as",
30
+ "the logged-in user and shares it with the service account as a writer, so the",
31
+ "active account must grant Drive access.",
29
32
  "",
30
33
  "Usage:",
31
34
  " hikoutei setup [options]",
@@ -41,10 +44,49 @@ export const SETUP_HELP_TEXT = [
41
44
  " the current directory).",
42
45
  " --yes Skip interactive confirmation (non-interactive",
43
46
  " mode).",
44
- " --dry-run Print the exact gcloud command sequence and",
45
- " simulated outcomes without executing anything.",
47
+ " --dry-run Print the exact command sequence and",
48
+ " simulated outcomes without executing anything",
49
+ " (read-only local path-safety checks only;",
50
+ " no subprocess, network, cloud, or file",
51
+ " mutations; the gcloud key create shows the",
52
+ " private staging placeholder",
53
+ " <private-key-staging-dir>/key.json — never the",
54
+ " final key path).",
46
55
  " -h, --help Show this help and exit.",
47
56
  "",
57
+ "Automatic setup runs on macOS and Linux. On Windows, non-dry-run setup",
58
+ "is refused before any subprocess, network, cloud, lock, checkpoint, key,",
59
+ "or file mutation (Windows cannot guarantee no-follow or owner-only ACL",
60
+ "semantics); manual setup remains available.",
61
+ "",
62
+ "Interrupted runs resume from .hikoutei-setup-state.json in the current",
63
+ "directory. A spreadsheet create whose outcome is unknown is reconciled by",
64
+ "its creation marker on the next run; setup never creates a second",
65
+ "spreadsheet. A create rejected up front (HTTP 400/403) with no matching",
66
+ "file rolls the checkpoint back to key_ready so a corrected rerun starts a",
67
+ "fresh marker. The service-account key is created under a write-ahead",
68
+ "contract: the user-managed key list is recorded as a baseline before the",
69
+ "single gcloud key create, and key_create_started/key_ready checkpoints",
70
+ "let a crashed run recover a staged or installed key instead of creating a",
71
+ "second one. Only the invocation that just persisted key_create_started",
72
+ "may issue the one key create; resumed runs are reconcile-only and poll",
73
+ "the key list plus staged/final evidence for up to two minutes (2, 4, 8,",
74
+ "16, 30, 30, 30 s) before failing with key_create_uncertain — the create",
75
+ "is never retried automatically. An unmatched user-managed key with no",
76
+ "local credential is never deleted automatically: setup fails with",
77
+ "key_create_uncertain and you inspect the key list in the Google Cloud",
78
+ "console before rerunning (verified-absent states require removing the",
79
+ "setup state file to reset the key checkpoint).",
80
+ "Reused keys are enforced to owner-only mode 600.",
81
+ "An exclusive lock directory (.hikoutei-setup-state.json.lock)",
82
+ "prevents concurrent runs and is never removed automatically: a leftover",
83
+ "lock directory (for example after a crash) requires manual removal only",
84
+ "when you are certain no setup is running.",
85
+ "Starting fresh requires removing or moving BOTH the checkpoint and the",
86
+ "service-account key file (or passing --project <id> to recover an",
87
+ "existing key); checkpointed or identity-matched cloud resources are",
88
+ "reused, and setup never deletes cloud resources.",
89
+ "",
48
90
  ].join("\n");
49
91
  /** True when the flag is a value flag; used to accept `--flag value` and `--flag=value`. */
50
92
  const VALUE_FLAGS = [
@@ -96,9 +138,31 @@ export function parseSetupArgs(argv) {
96
138
  }
97
139
  switch (flagName) {
98
140
  case SETUP_FLAGS.PROJECT:
141
+ // Strict GCP project id format (the canonical shared guard): an
142
+ // option-like or malformed value (for example `--project=--flag`)
143
+ // is rejected BEFORE it can reach gcloud, an API, or a file.
144
+ if (!isValidGcpProjectId(value)) {
145
+ return {
146
+ status: "invalid",
147
+ failure: setupFailure(SETUP_ERROR_CODES.INVALID_ARGS, `invalid value for ${flagName}: GCP project ids must start with a lowercase ` +
148
+ `letter and contain only lowercase letters, digits, and hyphens (6-30 characters)`),
149
+ };
150
+ }
99
151
  projectId = value;
100
152
  break;
101
153
  case SETUP_FLAGS.SA_NAME:
154
+ // Strict service-account name format (the canonical shared guard):
155
+ // an option-like or malformed value (for example
156
+ // `--sa-name=--flag`) is rejected before it can reach gcloud, an
157
+ // API, or a file.
158
+ if (!isValidServiceAccountName(value)) {
159
+ return {
160
+ status: "invalid",
161
+ failure: setupFailure(SETUP_ERROR_CODES.INVALID_ARGS, `invalid value for ${flagName}: service-account names must start with a ` +
162
+ `lowercase letter and contain only lowercase letters, digits, and hyphens ` +
163
+ `(6-30 characters)`),
164
+ };
165
+ }
102
166
  saName = value;
103
167
  break;
104
168
  case SETUP_FLAGS.SPREADSHEET_TITLE:
@@ -1 +1 @@
1
- {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}