i-repo 2.14.0 → 2.15.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i-repo",
3
- "version": "2.14.0",
3
+ "version": "2.15.0",
4
4
  "description": "Modern CLI for ConMas i-Reporter - Built for humans and AI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -44,7 +44,7 @@ async function loadBuiltins() {
44
44
  }
45
45
 
46
46
  const PLUGIN = "i-repo-archive";
47
- const VERSION = "0.6.2";
47
+ const VERSION = "0.6.3";
48
48
  const PLUGIN_API = "1";
49
49
  const defaultArchiveRoot = () => join(homedir(), ".i-repo", "archives");
50
50
 
@@ -179,6 +179,19 @@ if (arg0 === "--plugin-schema") {
179
179
  { name: "--cleanup", type: "boolean", subcommand: "push-s3", destructive: true,
180
180
  label: "Clean up local archive",
181
181
  description: "Delete the local archive directory after the upload is verified" },
182
+ // push-s3 無人認証(#92・push-azure と同作法): 値は argv ではなく env で aws に渡す。
183
+ { name: "--access-key-id", type: "string", subcommand: "push-s3", envVar: "AWS_ACCESS_KEY_ID",
184
+ label: "AWS アクセスキーID(任意・無人用)",
185
+ description: "IAM アクセスキーID。値は環境変数 AWS_ACCESS_KEY_ID で aws に渡す(対話 aws sso login 不要で無人化)" },
186
+ { name: "--secret-access-key", type: "string", subcommand: "push-s3", secret: true, envVar: "AWS_SECRET_ACCESS_KEY",
187
+ label: "AWS シークレットアクセスキー(任意・無人用)",
188
+ description: "IAM シークレットアクセスキー。値は argv に出さず環境変数 AWS_SECRET_ACCESS_KEY で aws に渡す" },
189
+ { name: "--profile", type: "string", subcommand: "push-s3", envVar: "AWS_PROFILE",
190
+ label: "AWS プロファイル(任意)",
191
+ description: "named profile(~/.aws 構成)。値は環境変数 AWS_PROFILE で aws に渡す" },
192
+ { name: "--region", type: "string", subcommand: "push-s3", envVar: "AWS_REGION",
193
+ label: "AWS リージョン(任意)",
194
+ description: "リージョン。値は環境変数 AWS_REGION で aws に渡す" },
182
195
  // push-gcs
183
196
  { name: "--to", type: "string", required: true, subcommand: "push-gcs",
184
197
  label: "GCS destination", placeholder: "gs://bucket/prefix",
@@ -190,6 +203,10 @@ if (arg0 === "--plugin-schema") {
190
203
  { name: "--cleanup", type: "boolean", subcommand: "push-gcs", destructive: true,
191
204
  label: "Clean up local archive",
192
205
  description: "Delete the local archive directory after the upload is verified" },
206
+ // push-gcs 無人認証(#92): SA 鍵 JSON の**パス**を env(GOOGLE_APPLICATION_CREDENTIALS)で gcloud に渡す。
207
+ { name: "--gcp-credentials", type: "string", subcommand: "push-gcs", envVar: "GOOGLE_APPLICATION_CREDENTIALS",
208
+ label: "GCP サービスアカウント鍵のパス(任意・無人用)",
209
+ description: "サービスアカウント鍵 JSON のファイルパス(鍵そのものではない)。env GOOGLE_APPLICATION_CREDENTIALS で受け、プラグインが gcloud CLI 用に CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE へも複写して無人化(対話 gcloud auth login 不要)" },
193
210
  // push-azure
194
211
  { name: "--to", type: "string", required: true, subcommand: "push-azure",
195
212
  label: "Azure Blob destination", placeholder: "https://<account>.blob.core.windows.net/<container>/<prefix>",
@@ -222,8 +239,13 @@ if (arg0 === "--plugin-schema") {
222
239
  // pull-*(取り戻し・host 管理。GUI 配信フォームには出ない=mode:read。Rust が固定引数で渡す)
223
240
  { name: "--from", type: "string", subcommand: "pull-s3", description: "取得元 s3://bucket/prefix(着地した bundle のルート)" },
224
241
  { name: "--out", type: "string", subcommand: "pull-s3", description: "取得先ローカルディレクトリ" },
242
+ { name: "--access-key-id", type: "string", subcommand: "pull-s3", envVar: "AWS_ACCESS_KEY_ID", description: "無人取り戻し用 IAM アクセスキーID(env AWS_ACCESS_KEY_ID)" },
243
+ { name: "--secret-access-key", type: "string", subcommand: "pull-s3", secret: true, envVar: "AWS_SECRET_ACCESS_KEY", description: "無人取り戻し用 IAM シークレットキー(env のみ・argv 非掲載)" },
244
+ { name: "--profile", type: "string", subcommand: "pull-s3", envVar: "AWS_PROFILE", description: "AWS named profile(env AWS_PROFILE)" },
245
+ { name: "--region", type: "string", subcommand: "pull-s3", envVar: "AWS_REGION", description: "AWS リージョン(env AWS_REGION)" },
225
246
  { name: "--from", type: "string", subcommand: "pull-gcs", description: "取得元 gs://bucket/prefix" },
226
247
  { name: "--out", type: "string", subcommand: "pull-gcs", description: "取得先ローカルディレクトリ" },
248
+ { name: "--gcp-credentials", type: "string", subcommand: "pull-gcs", envVar: "GOOGLE_APPLICATION_CREDENTIALS", description: "無人取り戻し用 SA 鍵 JSON のパス(env GOOGLE_APPLICATION_CREDENTIALS)" },
227
249
  { name: "--from", type: "string", subcommand: "pull-azure", description: "取得元 https://<account>.blob.core.windows.net/<container>/<prefix>" },
228
250
  { name: "--out", type: "string", subcommand: "pull-azure", description: "取得先ローカルディレクトリ" },
229
251
  { name: "--sas", type: "string", subcommand: "pull-azure", secret: true, envVar: "AZURE_STORAGE_SAS_TOKEN",
@@ -350,15 +372,23 @@ function usage() {
350
372
  --history --regist-from --regist-to --update-from --update-to
351
373
  -k/--system-key <n=v> (repeatable)
352
374
  ${PLUGIN} push-s3 <archive-dir> --to s3://bucket/prefix [--cleanup] [--dry-run]
375
+ [--access-key-id <id> --secret-access-key <key> | --profile <name>] [--region <r>]
353
376
  ${PLUGIN} push-gcs <archive-dir> --to gs://bucket/prefix [--cleanup] [--dry-run]
377
+ [--gcp-credentials <service-account-key.json path>]
354
378
  ${PLUGIN} push-azure <archive-dir> --to https://<account>.blob.core.windows.net/<container>/<prefix>
355
379
  [--sas <token> | --connection-string <cs>] [--cleanup] [--dry-run]
356
380
  ${PLUGIN} push-local <archive-dir> --to <folder|network-share path> [--cleanup] [--dry-run]
357
381
  --cleanup Delete the local archive after the upload is verified
358
382
  (gcs requires gcloud; azure requires az CLI. push-local needs no external CLI
359
383
  (Node fs copy) and accepts a plain folder or mounted network-share path.
360
- secrets are read from --sas/--connection-string or AZURE_STORAGE_* env and
361
- passed to az via env, never argv)`);
384
+ Unattended creds are read from the flags above OR env
385
+ (s3: AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_PROFILE/AWS_REGION; gcs:
386
+ GOOGLE_APPLICATION_CREDENTIALS; azure: AZURE_STORAGE_*) and passed to the
387
+ cloud CLI via env, never argv — no interactive login needed.
388
+ Note: AWS keys are a pair (both required); --profile and IAM keys are mutually
389
+ exclusive. When run under \`i-repo\` (dispatch/deliver) the parent env is
390
+ allow-listed, so pass creds via these flags, host env-injection, or
391
+ \`i-repo config set pluginPassEnv "AWS_*,GOOGLE_APPLICATION_CREDENTIALS,AZURE_STORAGE_*"\`)`);
362
392
  }
363
393
 
364
394
  // ── Tiny argv parser (no dependencies) ─────────────────────────────────────
@@ -475,8 +505,13 @@ function normalizeLocalDest(to) {
475
505
  function parsePushArgs(argv, backend) {
476
506
  const label = `push-${backend.store}`;
477
507
  const spec = { "--to": "value", "--prefix": "value", "--dry-run": "flag", "--cleanup": "flag" };
478
- // Azure は認証 secret を受ける(値は argv に出さず env az に渡す。buildPushEnv 参照)。
508
+ // 無人認証フラグ(#92)。secret 値は argv に出さず env でクラウド CLI に渡す(buildPushEnv 参照)。
479
509
  if (backend.store === "azure") { spec["--sas"] = "value"; spec["--connection-string"] = "value"; }
510
+ if (backend.store === "s3") {
511
+ spec["--access-key-id"] = "value"; spec["--secret-access-key"] = "value";
512
+ spec["--profile"] = "value"; spec["--region"] = "value";
513
+ }
514
+ if (backend.store === "gcs") { spec["--gcp-credentials"] = "value"; }
480
515
  const o = parseArgv(argv, spec, label);
481
516
  if (o._.length !== 1) throw new Error(`${label} requires exactly one <archive-dir> argument.`);
482
517
  // local は scheme 付き URL ではなくファイルパス(フォルダ/ネットワーク共有)。scheme 検査を外し、
@@ -499,6 +534,10 @@ function parsePushArgs(argv, backend) {
499
534
  out.sas = o.sas || process.env.AZURE_STORAGE_SAS_TOKEN || "";
500
535
  out.connectionString = o["connection-string"] || process.env.AZURE_STORAGE_CONNECTION_STRING || "";
501
536
  }
537
+ // s3/gcs 無人認証(#92)。フラグ指定時のみ拾う(未指定なら ambient/host 注入の env が
538
+ // buildPushEnv の {...process.env} で素通り=envVar 宣言と整合)。
539
+ if (backend.store === "s3") Object.assign(out, s3CredsFromArgs(o, label));
540
+ if (backend.store === "gcs") out.gcpCredentials = o["gcp-credentials"] || "";
502
541
  return out;
503
542
  }
504
543
 
@@ -666,6 +705,26 @@ function joinUri(prefix, child) {
666
705
  }
667
706
 
668
707
  // secret(SAS / 接続文字列)は argv に載せず az が読む環境変数で渡す(AGENTS.md / 本番化方針)。
708
+ /**
709
+ * s3 無人認証フラグを検証して取り出す(#92)。IAM キーは**対**でのみ意味を持つ
710
+ * (AWS は片方だけだと "Partial credentials" で失敗し、明示キーは profile/ambient より
711
+ * 優先されるため)。キーと --profile の併用も aws では profile が黙殺されるので拒否する
712
+ * (usage は排他表記)。フラグ無指定時は ambient/host 注入の env が素通り。
713
+ */
714
+ function s3CredsFromArgs(o, label) {
715
+ const accessKeyId = o["access-key-id"] || "";
716
+ const secretAccessKey = o["secret-access-key"] || "";
717
+ const profile = o.profile || "";
718
+ const region = o.region || "";
719
+ if (Boolean(accessKeyId) !== Boolean(secretAccessKey)) {
720
+ throw new Error(`${label}: --access-key-id and --secret-access-key must be provided together.`);
721
+ }
722
+ if ((accessKeyId || secretAccessKey) && profile) {
723
+ throw new Error(`${label}: use either IAM keys (--access-key-id/--secret-access-key) or --profile, not both.`);
724
+ }
725
+ return { accessKeyId, secretAccessKey, profile, region };
726
+ }
727
+
669
728
  function buildPushEnv(options) {
670
729
  const env = { ...process.env };
671
730
  if (options.connectionString) env.AZURE_STORAGE_CONNECTION_STRING = options.connectionString;
@@ -674,6 +733,21 @@ function buildPushEnv(options) {
674
733
  // RBAC-only / listKeys 無効アカウントで失敗するため・Codex #76 P2)。s3/gcs は options.azure
675
734
  // 未設定なので素通り。
676
735
  else if (options.azure) env.AZURE_STORAGE_AUTH_MODE = "login";
736
+ // s3 無人認証(#92): フラグ指定時に env を上書き。未指定なら ambient/host 注入が素通り。
737
+ if (options.accessKeyId) env.AWS_ACCESS_KEY_ID = options.accessKeyId;
738
+ if (options.secretAccessKey) env.AWS_SECRET_ACCESS_KEY = options.secretAccessKey;
739
+ if (options.profile) env.AWS_PROFILE = options.profile;
740
+ // AWS_REGION(CLI v2)と AWS_DEFAULT_REGION(v1/botocore 系)の双方を立てる。
741
+ if (options.region) { env.AWS_REGION = options.region; env.AWS_DEFAULT_REGION = options.region; }
742
+ // gcs 無人認証(#92): SA 鍵パスを env で渡す(対話 login 不要)。
743
+ // GOOGLE_APPLICATION_CREDENTIALS は ADC/クライアントライブラリ用で、**gcloud CLI 自体は
744
+ // 読まない**(gcloud は CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE を読む・Codex #93 P1)。
745
+ // 両方を立てて gcloud storage と client-lib の双方をカバーする。フラグが無くても
746
+ // ambient/host 注入の GOOGLE_APPLICATION_CREDENTIALS があれば gcloud 用に複写する。
747
+ if (options.gcpCredentials) env.GOOGLE_APPLICATION_CREDENTIALS = options.gcpCredentials;
748
+ if (env.GOOGLE_APPLICATION_CREDENTIALS && !env.CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE) {
749
+ env.CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE = env.GOOGLE_APPLICATION_CREDENTIALS;
750
+ }
677
751
  return env;
678
752
  }
679
753
 
@@ -876,7 +950,13 @@ async function pushArchiveBundle(options, backend) {
876
950
  function parsePullArgs(argv, backend) {
877
951
  const label = `pull-${backend.store}`;
878
952
  const spec = { "--from": "value", "--out": "value" };
953
+ // 無人認証(#92・push と対称): pull も対話ログイン無しで取り戻せる。
879
954
  if (backend.store === "azure") { spec["--sas"] = "value"; spec["--connection-string"] = "value"; }
955
+ if (backend.store === "s3") {
956
+ spec["--access-key-id"] = "value"; spec["--secret-access-key"] = "value";
957
+ spec["--profile"] = "value"; spec["--region"] = "value";
958
+ }
959
+ if (backend.store === "gcs") { spec["--gcp-credentials"] = "value"; }
880
960
  const o = parseArgv(argv, spec, label);
881
961
  if (!o.from) throw new Error(`${label} requires --from ${backend.scheme || "<source>"}…`);
882
962
  if (!o.out) throw new Error(`${label} requires --out <local-dir>.`);
@@ -895,6 +975,8 @@ function parsePullArgs(argv, backend) {
895
975
  out.sas = o.sas || process.env.AZURE_STORAGE_SAS_TOKEN || "";
896
976
  out.connectionString = o["connection-string"] || process.env.AZURE_STORAGE_CONNECTION_STRING || "";
897
977
  }
978
+ if (backend.store === "s3") Object.assign(out, s3CredsFromArgs(o, label));
979
+ if (backend.store === "gcs") out.gcpCredentials = o["gcp-credentials"] || "";
898
980
  return out;
899
981
  }
900
982