@topolo/cli 0.6.1 → 0.6.4

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.
@@ -288,6 +288,7 @@ function emitWranglerToml(targetName, target) {
288
288
  lines.push(`directory = ${tomlString(target.assets.directory || target.outputDir || 'dist')}`);
289
289
  if (target.assets.binding) lines.push(`binding = ${tomlString(target.assets.binding)}`);
290
290
  else lines.push(`binding = "ASSETS"`);
291
+ if (target.assets.htmlHandling) lines.push(`html_handling = ${tomlString(target.assets.htmlHandling)}`);
291
292
  if (target.assets.notFoundHandling) lines.push(`not_found_handling = ${tomlString(target.assets.notFoundHandling)}`);
292
293
  if (target.assets.runWorkerFirst !== undefined) lines.push(`run_worker_first = ${tomlString(target.assets.runWorkerFirst)}`);
293
294
  lines.push('');
@@ -390,6 +391,7 @@ function emitWranglerToml(targetName, target) {
390
391
  lines.push(`[env.${env}.assets]`);
391
392
  lines.push(`directory = ${tomlString(target.assets.directory || target.outputDir || 'dist')}`);
392
393
  lines.push(`binding = ${tomlString(target.assets.binding || 'ASSETS')}`);
394
+ if (target.assets.htmlHandling) lines.push(`html_handling = ${tomlString(target.assets.htmlHandling)}`);
393
395
  if (target.assets.notFoundHandling) lines.push(`not_found_handling = ${tomlString(target.assets.notFoundHandling)}`);
394
396
  if (target.assets.runWorkerFirst !== undefined) lines.push(`run_worker_first = ${tomlString(target.assets.runWorkerFirst)}`);
395
397
  lines.push('');
@@ -572,6 +574,20 @@ function emitBindings(lines, bindings, env) {
572
574
  lines.push(`service = ${tomlString(service)}`);
573
575
  lines.push('');
574
576
  }
577
+ // Cloudflare Secrets Store bindings — the durable data-at-rest key escrow
578
+ // (docs/data-at-rest-encryption-architecture.md). Store ids differ per env
579
+ // (per-env Cloudflare accounts), so the shape mirrors d1/kv: per-env config
580
+ // objects under the binding.
581
+ for (const s of bindings.secretsStore || []) {
582
+ if (!bindingAppliesToEnv(s, env)) continue;
583
+ const cfg = s[env];
584
+ if (!cfg) continue;
585
+ lines.push(`[[env.${env}.secrets_store_secrets]]`);
586
+ lines.push(`binding = ${tomlString(s.binding)}`);
587
+ lines.push(`store_id = ${tomlString(cfg.storeId)}`);
588
+ lines.push(`secret_name = ${tomlString(cfg.secretName)}`);
589
+ lines.push('');
590
+ }
575
591
  for (const a of bindings.ai || []) {
576
592
  lines.push(`[env.${env}.ai]`);
577
593
  lines.push(`binding = ${tomlString(a.binding)}`);
@@ -595,7 +611,7 @@ function emitCloudcontrol() {
595
611
  deployableTargets.flatMap((target) => target.environments || ENVS),
596
612
  );
597
613
  cc.deploy_method = deployableTargets.length ? 'wrangler' : 'none';
598
- cc.ci_provider = existing.ci_provider || 'github_actions';
614
+ cc.ci_provider = existing.ci_provider || 'local';
599
615
  cc.quality_policy = existing.quality_policy || {
600
616
  profile: 'first_party_app',
601
617
  coverage: { mode: 'ratchet' },
package/dist/index.js CHANGED
@@ -277,7 +277,9 @@ var APPLICATIONS = {
277
277
  "domains": [
278
278
  "brand.topolo.app"
279
279
  ],
280
- "routes": [],
280
+ "routes": [
281
+ "brand.topolo.app"
282
+ ],
281
283
  "appId": "brand"
282
284
  },
283
285
  {
@@ -307,7 +309,9 @@ var APPLICATIONS = {
307
309
  "domains": [
308
310
  "bugfix.topolo.app"
309
311
  ],
310
- "routes": [],
312
+ "routes": [
313
+ "bugfix.topolo.app"
314
+ ],
311
315
  "appId": "bugfix"
312
316
  }
313
317
  ]
@@ -361,7 +365,9 @@ var APPLICATIONS = {
361
365
  "domains": [
362
366
  "calendar.topolo.app"
363
367
  ],
364
- "routes": [],
368
+ "routes": [
369
+ "calendar.topolo.app"
370
+ ],
365
371
  "appId": "calendar"
366
372
  },
367
373
  {
@@ -421,7 +427,9 @@ var APPLICATIONS = {
421
427
  "domains": [
422
428
  "capacity.topolo.app"
423
429
  ],
424
- "routes": [],
430
+ "routes": [
431
+ "capacity.topolo.app"
432
+ ],
425
433
  "appId": "capacity"
426
434
  }
427
435
  ]
@@ -443,7 +451,9 @@ var APPLICATIONS = {
443
451
  "domains": [
444
452
  "chat.topolo.app"
445
453
  ],
446
- "routes": [],
454
+ "routes": [
455
+ "chat.topolo.app"
456
+ ],
447
457
  "appId": "chat"
448
458
  },
449
459
  {
@@ -1003,7 +1013,9 @@ var APPLICATIONS = {
1003
1013
  "domains": [
1004
1014
  "mail.topolo.app"
1005
1015
  ],
1006
- "routes": [],
1016
+ "routes": [
1017
+ "mail.topolo.app"
1018
+ ],
1007
1019
  "appId": "mail"
1008
1020
  },
1009
1021
  {
@@ -1163,7 +1175,9 @@ var APPLICATIONS = {
1163
1175
  "domains": [
1164
1176
  "observability-watch.topolo.app"
1165
1177
  ],
1166
- "routes": [],
1178
+ "routes": [
1179
+ "observability-watch.topolo.app"
1180
+ ],
1167
1181
  "appId": "observability_watch"
1168
1182
  }
1169
1183
  ]
@@ -1798,7 +1812,7 @@ var APPLICATION_REQUIREMENTS = [
1798
1812
  "Use TopoloAppMetricCard, TopoloAppEmptyState, TopoloAppStatusBadge, TopoloAppGrid, and TopoloAppSection for repeated app body patterns",
1799
1813
  "Keep visual QA fixtures available through visualQa=1 or __devpreview=1 so screenshot checks do not depend on live API state",
1800
1814
  "Keep mobile and desktop shell behavior aligned with the platform UI kit",
1801
- "Constrain app-owned workspace wrappers with min-width: 0, width: auto, and viewport-aware max-width so shell padding cannot create page-level horizontal overflow"
1815
+ "Constrain the app workspace-view layout wrappers with min-width: 0, width: auto, and viewport-aware max-width so shell padding cannot create page-level horizontal overflow"
1802
1816
  ]
1803
1817
  },
1804
1818
  {
@@ -3403,6 +3417,7 @@ var CrmModule = class {
3403
3417
  constructor(client) {
3404
3418
  this.client = client;
3405
3419
  }
3420
+ client;
3406
3421
  async listContacts(options = {}) {
3407
3422
  const res = await this.client.request({
3408
3423
  service: "crm",
@@ -3448,6 +3463,7 @@ var IdentityModule = class {
3448
3463
  constructor(client) {
3449
3464
  this.client = client;
3450
3465
  }
3466
+ client;
3451
3467
  /** Returns the resolved user, organization, and permission set for the
3452
3468
  * current credential. Equivalent to `TopoloClient.introspect()` — exposed
3453
3469
  * on this module for symmetry with the other domain modules. */
@@ -9461,20 +9477,13 @@ function scaffoldFiles(options) {
9461
9477
  `CREATE TABLE IF NOT EXISTS ${tablePrefix}_workspaces (`,
9462
9478
  " id TEXT PRIMARY KEY,",
9463
9479
  ` ${tenantColumn} TEXT NOT NULL,`,
9464
- " name TEXT NOT NULL,",
9465
- " slug TEXT NOT NULL,",
9466
- " created_by_user_id TEXT,",
9467
- " created_by_email TEXT,",
9480
+ " status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'archived')),",
9468
9481
  " created_at TEXT NOT NULL,",
9469
- " updated_at TEXT NOT NULL,",
9470
- ` UNIQUE(${tenantColumn}, slug)`,
9482
+ " updated_at TEXT NOT NULL",
9471
9483
  ");",
9472
9484
  "",
9473
9485
  `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workspaces_${tenantColumn}`,
9474
9486
  ` ON ${tablePrefix}_workspaces(${tenantColumn});`,
9475
- "",
9476
- `CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workspaces_slug`,
9477
- ` ON ${tablePrefix}_workspaces(${tenantColumn}, slug);`,
9478
9487
  ""
9479
9488
  ].join("\n");
9480
9489
  const base = target === "platform" ? firstPartyAppPath(application.appDir, options.payload.audience) : application.appDir;
@@ -10037,10 +10046,10 @@ export default defineConfig({
10037
10046
  if (options.payload.resources.d1) {
10038
10047
  files.push({
10039
10048
  path: `${apiBase}/migrations/0001_initial.sql`,
10040
- purpose: "Canonical multi-tenant baseline: the app workspaces table.",
10049
+ purpose: "Canonical multi-tenant baseline: the identity-only workspace mirror (platform owns the record).",
10041
10050
  requiredSignals: [
10042
- `${tablePrefix}_workspaces carries ${tenantColumn} on every row`,
10043
- "every domain table added later carries the tenant + workspace columns"
10051
+ `${tablePrefix}_workspaces is an identity-only mirror (id, ${tenantColumn}, status) \u2014 no name/slug/is_default; the workspace record lives in TopoloAuth`,
10052
+ `every domain table added later carries ${tenantColumn} and a workspace_id scope column`
10044
10053
  ],
10045
10054
  content: workspacesMigrationSql
10046
10055
  });
@@ -10332,6 +10341,22 @@ async function reconcileApplicationCapabilitySource(options) {
10332
10341
  distributionModel: registration.distributionModel === "marketplace" ? "marketplace" : "organization_internal",
10333
10342
  requested: [...existing, ...options.additions ?? []]
10334
10343
  });
10344
+ const marketplace = record(registration.marketplace);
10345
+ const unlistedNativeArtifact = options.ownerType === "topolo_first_party" && registration.surfaceModel === "mobile_container" && registration.distributionModel === "organization_internal" && marketplace?.intent === "unlisted";
10346
+ if (unlistedNativeArtifact) {
10347
+ return {
10348
+ mode: options.mode,
10349
+ applied: false,
10350
+ status: "in_sync",
10351
+ manifestPath,
10352
+ packagePath,
10353
+ contractPath,
10354
+ capabilities,
10355
+ changes: [],
10356
+ missingResources: [],
10357
+ verticalConfiguration: []
10358
+ };
10359
+ }
10335
10360
  const expectedComposition = capabilityCompositionProjection(capabilities);
10336
10361
  const expectedNotifications = capabilities.selected.includes("notification_producer") ? { role: "producer", contracts: "topolo.notification-contracts.json" } : capabilities.selected.includes("notifications") ? { role: "consumer_only" } : { role: "internal_non_producer" };
10337
10362
  const changes = [];
@@ -10598,6 +10623,9 @@ function resolveManifestApplicationUrl(manifest, environment) {
10598
10623
  if (hostOverride) return `https://${hostOverride.replace(/^https?:\/\//, "").replace(/\/+$/, "")}`;
10599
10624
  const domain = manifest.environments?.[environment]?.domain;
10600
10625
  if (!target.subdomain || !domain) {
10626
+ if (manifest.registration?.productionUrl) {
10627
+ return manifest.registration.productionUrl.replace(/\/+$/, "");
10628
+ }
10601
10629
  throw new Error(`Cannot derive the ${environment} application URL from target ${targetName}.`);
10602
10630
  }
10603
10631
  return `https://${target.subdomain}.${domain}`;
@@ -10623,10 +10651,11 @@ function assertRegistration(value) {
10623
10651
  "version",
10624
10652
  "pricing",
10625
10653
  "supportEmail",
10626
- "auth",
10627
10654
  "capabilities",
10628
10655
  "marketplace"
10629
10656
  ];
10657
+ const marketplace = record2(registration?.marketplace);
10658
+ if (marketplace?.intent !== "unlisted") required.push("auth");
10630
10659
  const missing = required.filter((field) => registration?.[field] == null || registration[field] === "");
10631
10660
  if (missing.length) {
10632
10661
  throw new Error(
@@ -10730,7 +10759,7 @@ async function loadApplicationReconcileRequest(options) {
10730
10759
  }
10731
10760
  const environment = options.environment || selectedEnvironment();
10732
10761
  const productionUrl = resolveManifestApplicationUrl(manifest, environment);
10733
- const callbackPath = registration.auth.callbackPath.startsWith("/") ? registration.auth.callbackPath : `/${registration.auth.callbackPath}`;
10762
+ const callbackPath = registration.auth ? registration.auth.callbackPath.startsWith("/") ? registration.auth.callbackPath : `/${registration.auth.callbackPath}` : null;
10734
10763
  const appId = String(manifest.appId || manifest.app_id || "").trim();
10735
10764
  if (!appId) throw new Error("topolo.app.json must declare the immutable appId.");
10736
10765
  return {
@@ -10760,8 +10789,8 @@ async function loadApplicationReconcileRequest(options) {
10760
10789
  supportEmail: registration.supportEmail,
10761
10790
  tags: registration.tags ?? [],
10762
10791
  screenshots: registration.screenshots ?? [],
10763
- callbackUrls: [`${productionUrl}${callbackPath}`],
10764
- requestedScopes: registration.auth.requestedScopes,
10792
+ callbackUrls: callbackPath ? [`${productionUrl}${callbackPath}`] : [],
10793
+ requestedScopes: registration.auth?.requestedScopes ?? [],
10765
10794
  capabilities: registration.capabilities,
10766
10795
  marketplace: { ...registration.marketplace, appUrl: productionUrl },
10767
10796
  notifications: manifest.notifications ?? null
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@topolo/cli",
3
- "version": "0.6.1",
4
- "topoloPublishedVersion": "0.6.1",
3
+ "version": "0.6.4",
4
+ "topoloPublishedVersion": "0.6.4",
5
5
  "description": "Command-line interface for Topolo developers, operators, and agents, with internal first-party scaffolding available under the topolo platform namespace.",
6
6
  "type": "module",
7
7
  "bin": {
@@ -12,7 +12,7 @@
12
12
  "skills"
13
13
  ],
14
14
  "scripts": {
15
- "build:sdk": "pnpm --dir ../topolo-sdk build",
15
+ "build:sdk": "python3 ../../tooling/with-resource-lock.py ../topolo-sdk -- pnpm --dir ../topolo-sdk build",
16
16
  "prebuild": "pnpm run build:sdk",
17
17
  "build": "tsup && node scripts/vendor-generator.mjs",
18
18
  "dev": "tsup --watch",