@topolo/cli 0.6.10 → 0.7.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/dist/index.js CHANGED
@@ -110,57 +110,8 @@ var TopoloHttpError = class extends TopoloSdkError {
110
110
  }
111
111
  };
112
112
  var APP_API_URLS = {
113
- agent: "https://agent.topolo.app",
114
113
  auth: "https://auth.topolo.app",
115
- backup: "https://backup.topolo.app",
116
- blog: "https://blog.topolo.app",
117
- books: "https://books.topolo.app",
118
- brand: "https://brand.topolo.app",
119
- bugfix: "https://bugfix.topolo.app",
120
- bytes: "https://bytes.topolo.app",
121
- calendar: "https://calendar.topolo.app",
122
- campaigns: "https://campaigns.topolo.app",
123
- capacity: "https://capacity.topolo.app",
124
- chat: "https://chat.topolo.app",
125
- commerce: "https://commerce.topolo.app",
126
- compose: "https://compose.topolo.app",
127
- consent: "https://consent.topolo.app",
128
- crm: "https://crm.topolo.app",
129
- design: "https://design.topolo.app",
130
- developers: "https://developers.topolo.app",
131
- director: "https://director.topolo.app",
132
- feed: "https://feed.topolo.app",
133
- flow: "https://flow.topolo.app",
134
- forecast: "https://forecast.topolo.app",
135
- forms: "https://forms.topolo.app",
136
- home: "https://home.topolo.app",
137
- insights: "https://insights.topolo.app",
138
- inventory: "https://inventory.topolo.app",
139
- learn: "https://learn.topolo.app",
140
- localize: "https://localize.topolo.app",
141
- mail: "https://mail.topolo.app",
142
- mdm: "https://mdm.topolo.app",
143
- messages: "https://messages.topolo.app",
144
- nexus: "https://nexus.topolo.app",
145
- notify: "https://notify.topolo.app",
146
- observability_watch: "https://observability-watch.topolo.app",
147
- one: "https://www.topolo.app",
148
- p2p: "https://p2p.topolo.app",
149
- pay: "https://pay.topolo.app",
150
- people: "https://people.topolo.app",
151
- "quro.api": "https://api.ol0.me",
152
- "quro.redirect": "https://ol0.me",
153
- roadmapper: "https://roadmapper.topolo.app",
154
- sign: "https://sign.topolo.app",
155
- social_studio: "https://studio.topolo.app",
156
- socialize: "https://socialize.topolo.app",
157
- spaces: "https://spaces.topolo.app",
158
- status: "https://status.topolo.app",
159
- success: "https://success.topolo.app",
160
- support: "https://support.topolo.app",
161
- survey: "https://survey.topolo.app",
162
- voice: "https://voice.topolo.app",
163
- web: "https://web.topolo.app"
114
+ developers: "https://developers.topolo.app"
164
115
  };
165
116
  var APPLICATIONS = {
166
117
  "admin": {
@@ -1886,7 +1837,145 @@ var APPLICATIONS = {
1886
1837
  ]
1887
1838
  }
1888
1839
  };
1889
- var APPLICATION_REQUIREMENTS_VERSION = "2026-06-07.1";
1840
+ function friendlyAppId(entry) {
1841
+ for (const value of [entry.slug, entry.name, entry.appId]) {
1842
+ if (typeof value !== "string" || !value.trim()) continue;
1843
+ const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
1844
+ const withoutPrefix = normalized.replace(/^(?:app[_-])?topolo[-_]+/, "");
1845
+ if (withoutPrefix) return withoutPrefix;
1846
+ }
1847
+ return entry.appId;
1848
+ }
1849
+ function idVariants(value) {
1850
+ const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
1851
+ return [.../* @__PURE__ */ new Set([
1852
+ normalized,
1853
+ normalized.replace(/-/g, "_"),
1854
+ normalized.replace(/_/g, "-")
1855
+ ])].filter(Boolean);
1856
+ }
1857
+ var STATIC_APPLICATIONS = APPLICATIONS;
1858
+ function staticApplicationForId(id) {
1859
+ for (const variant of idVariants(id)) {
1860
+ const entry = STATIC_APPLICATIONS[variant];
1861
+ if (entry) return entry;
1862
+ }
1863
+ return null;
1864
+ }
1865
+ function applicationEntryFromCatalog(live) {
1866
+ const id = friendlyAppId(live);
1867
+ return {
1868
+ id,
1869
+ appDir: "-",
1870
+ name: live.name ?? live.slug ?? live.appId,
1871
+ packageName: null,
1872
+ productionUrl: live.launchUrl ?? live.apiBaseUrl ?? null,
1873
+ services: live.apiBaseUrl ? [id] : [],
1874
+ deployTargets: []
1875
+ };
1876
+ }
1877
+ var DIRECTORY_PAGE_LIMIT = 100;
1878
+ var DIRECTORY_MAX_PAGES = 100;
1879
+ function staticApplicationDirectory() {
1880
+ const applications = Object.entries(STATIC_APPLICATIONS).map(([id, application]) => ({
1881
+ id,
1882
+ application,
1883
+ source: "static",
1884
+ live: null
1885
+ })).sort((left, right) => left.id.localeCompare(right.id));
1886
+ return { source: "static_fallback", applications };
1887
+ }
1888
+ function directoryApplicationFromLive(live) {
1889
+ const id = friendlyAppId(live);
1890
+ return {
1891
+ id,
1892
+ // Prefer the static snapshot's richer repo/deploy metadata when the live
1893
+ // registry confirms the app; synthesize from the live entry otherwise.
1894
+ application: staticApplicationForId(id) ?? applicationEntryFromCatalog(live),
1895
+ source: "live",
1896
+ live
1897
+ };
1898
+ }
1899
+ async function listApplicationDirectory(client) {
1900
+ if (!client) return staticApplicationDirectory();
1901
+ let services;
1902
+ try {
1903
+ services = [];
1904
+ let cursor;
1905
+ for (let page = 0; page < DIRECTORY_MAX_PAGES; page += 1) {
1906
+ const result = await client.searchServices({
1907
+ ...cursor ? { cursor } : {},
1908
+ limit: DIRECTORY_PAGE_LIMIT
1909
+ });
1910
+ services.push(...result.services);
1911
+ if (!result.page.nextCursor) break;
1912
+ cursor = result.page.nextCursor;
1913
+ }
1914
+ } catch {
1915
+ return staticApplicationDirectory();
1916
+ }
1917
+ const seen = /* @__PURE__ */ new Map();
1918
+ for (const live of services) {
1919
+ const entry = directoryApplicationFromLive(live);
1920
+ if (!seen.has(entry.id)) seen.set(entry.id, entry);
1921
+ }
1922
+ return {
1923
+ source: "live",
1924
+ applications: [...seen.values()].sort((left, right) => left.id.localeCompare(right.id))
1925
+ };
1926
+ }
1927
+ function matchesDirectoryApplication(app, needle) {
1928
+ const candidates = new Set(idVariants(needle));
1929
+ const keys = [
1930
+ app.id,
1931
+ app.application.id,
1932
+ app.application.name,
1933
+ app.live?.appId,
1934
+ app.live?.slug,
1935
+ app.live?.name
1936
+ ];
1937
+ for (const key of keys) {
1938
+ if (typeof key !== "string" || !key.trim()) continue;
1939
+ for (const variant of idVariants(key)) {
1940
+ if (candidates.has(variant)) return true;
1941
+ }
1942
+ for (const variant of idVariants(friendlyAppId({ appId: key }))) {
1943
+ if (candidates.has(variant)) return true;
1944
+ }
1945
+ }
1946
+ return false;
1947
+ }
1948
+ function formatDirectoryApplicationIds(directory) {
1949
+ const ids = directory.applications.map((app) => app.id).sort();
1950
+ const preview = ids.slice(0, 50).join(", ");
1951
+ const suffix = ids.length > 50 ? `, ... +${ids.length - 50} more` : "";
1952
+ const label = directory.source === "live" ? "Applications available to this credential" : "Applications in the bundled static snapshot (live registry unreachable)";
1953
+ return `${label}: ${preview}${suffix}`;
1954
+ }
1955
+ async function resolveApplicationDirectoryEntry(client, application) {
1956
+ const needle = typeof application === "string" ? application.trim() : "";
1957
+ if (!needle) {
1958
+ throw new TopoloSdkError("unknown_application", "application is required");
1959
+ }
1960
+ if (client) {
1961
+ let live = null;
1962
+ try {
1963
+ live = await client.getService(needle);
1964
+ } catch {
1965
+ live = null;
1966
+ }
1967
+ if (live) return directoryApplicationFromLive(live);
1968
+ }
1969
+ const directory = await listApplicationDirectory(client);
1970
+ const match = directory.applications.find((app) => matchesDirectoryApplication(app, needle));
1971
+ if (match) return match;
1972
+ throw new TopoloSdkError(
1973
+ "unknown_application",
1974
+ `Unknown application "${application}". ${formatDirectoryApplicationIds(directory)}`
1975
+ );
1976
+ }
1977
+ var STATIC_APPLICATIONS2 = APPLICATIONS;
1978
+ var APPLICATION_REQUIREMENTS_VERSION = "2026-08-11.1";
1890
1979
  var APPLICATION_REQUIREMENTS = [
1891
1980
  {
1892
1981
  id: "platform-metadata",
@@ -1896,10 +1985,10 @@ var APPLICATION_REQUIREMENTS = [
1896
1985
  evidence: [
1897
1986
  "topolo.cloudcontrol.json exists for every deployed app surface",
1898
1987
  "package.json names the package or app when the repo ships code",
1899
- "The SDK application catalog exposes the app through topolo apps and MCP discovery"
1988
+ "The live platform registry exposes the app through topolo apps and MCP discovery"
1900
1989
  ],
1901
1990
  implementation: [
1902
- "Add the app to the SDK application catalog generator before exposing it to agents",
1991
+ "Register the app in the live platform registry (Auth service catalog) before exposing it to agents",
1903
1992
  "Keep production URLs, Worker names, Pages projects, routes, domains, and bindings current in CloudControl metadata",
1904
1993
  "Do not leave a new Topolo* app directory without an explicit application ID"
1905
1994
  ]
@@ -1974,7 +2063,7 @@ var APPLICATION_REQUIREMENTS = [
1974
2063
  implementation: [
1975
2064
  "Add production Worker api_url metadata and sdk_app_id for every agent-callable API target",
1976
2065
  "Mark browser, documentation, and runtime-only Worker targets with agent_callable:false",
1977
- "Expose stable app IDs through generated DEFAULT_APP_URLS and live catalog discovery",
2066
+ "Expose stable app IDs through live catalog discovery",
1978
2067
  "Keep typed SDK/CLI/MCP surfaces in sync when an API contract stabilizes"
1979
2068
  ]
1980
2069
  },
@@ -2094,15 +2183,24 @@ function applicationRequirementScopes(application) {
2094
2183
  }
2095
2184
  return Array.from(scopes);
2096
2185
  }
2186
+ function fallbackApplication(id) {
2187
+ const entry = STATIC_APPLICATIONS2[id];
2188
+ if (!entry) {
2189
+ throw new Error(
2190
+ `Unknown application "${id}" in the static fallback snapshot. Resolve applications from the live registry (resolveApplicationDirectoryEntry) and pass the entry directly.`
2191
+ );
2192
+ }
2193
+ return entry;
2194
+ }
2097
2195
  function requirementsForApplication(applicationOrId) {
2098
- const application = typeof applicationOrId === "string" ? APPLICATIONS[applicationOrId] : applicationOrId;
2196
+ const application = typeof applicationOrId === "string" ? fallbackApplication(applicationOrId) : applicationOrId;
2099
2197
  const scopes = new Set(applicationRequirementScopes(application));
2100
2198
  return APPLICATION_REQUIREMENTS.filter(
2101
2199
  (requirement) => requirement.appliesTo.some((scope) => scopes.has(scope))
2102
2200
  );
2103
2201
  }
2104
2202
  function auditApplicationRequirements(applicationOrId) {
2105
- const application = typeof applicationOrId === "string" ? APPLICATIONS[applicationOrId] : applicationOrId;
2203
+ const application = typeof applicationOrId === "string" ? fallbackApplication(applicationOrId) : applicationOrId;
2106
2204
  const scopes = applicationRequirementScopes(application);
2107
2205
  const findings = requirementsForApplication(application).map(
2108
2206
  (requirement) => evaluateRequirement(application, requirement)
@@ -2115,10 +2213,12 @@ function auditApplicationRequirements(applicationOrId) {
2115
2213
  findings
2116
2214
  };
2117
2215
  }
2118
- function auditAllApplicationRequirements(applicationIds = Object.keys(APPLICATIONS).sort()) {
2119
- const applications = applicationIds.map(
2120
- (applicationId) => auditApplicationRequirements(applicationId)
2216
+ function auditApplicationEntries(applications) {
2217
+ return buildAuditReport(
2218
+ applications.map((application) => auditApplicationRequirements(application))
2121
2219
  );
2220
+ }
2221
+ function buildAuditReport(applications) {
2122
2222
  const migrationQueue = applications.flatMap(
2123
2223
  (audit) => audit.findings.filter((finding2) => finding2.status !== "met").map((finding2) => ({
2124
2224
  applicationId: audit.application.id,
@@ -3421,8 +3521,9 @@ var TopoloClient = class _TopoloClient {
3421
3521
  });
3422
3522
  }
3423
3523
  /**
3424
- * Bundled generated registry for tooling that audits platform packaging, not
3425
- * for deciding what the current credential may use.
3524
+ * @deprecated Static fallback snapshot only. Use `searchServices()` (the
3525
+ * live credential-scoped registry) for anything that decides behavior; this
3526
+ * exists for offline packaging audits when the registry is unreachable.
3426
3527
  */
3427
3528
  listBundledServices() {
3428
3529
  const apps = Object.values(APPLICATIONS);
@@ -4079,57 +4180,8 @@ var TopoloHttpError2 = class extends TopoloSdkError2 {
4079
4180
  }
4080
4181
  };
4081
4182
  var APP_API_URLS2 = {
4082
- agent: "https://agent.topolo.app",
4083
4183
  auth: "https://auth.topolo.app",
4084
- backup: "https://backup.topolo.app",
4085
- blog: "https://blog.topolo.app",
4086
- books: "https://books.topolo.app",
4087
- brand: "https://brand.topolo.app",
4088
- bugfix: "https://bugfix.topolo.app",
4089
- bytes: "https://bytes.topolo.app",
4090
- calendar: "https://calendar.topolo.app",
4091
- campaigns: "https://campaigns.topolo.app",
4092
- capacity: "https://capacity.topolo.app",
4093
- chat: "https://chat.topolo.app",
4094
- commerce: "https://commerce.topolo.app",
4095
- compose: "https://compose.topolo.app",
4096
- consent: "https://consent.topolo.app",
4097
- crm: "https://crm.topolo.app",
4098
- design: "https://design.topolo.app",
4099
- developers: "https://developers.topolo.app",
4100
- director: "https://director.topolo.app",
4101
- feed: "https://feed.topolo.app",
4102
- flow: "https://flow.topolo.app",
4103
- forecast: "https://forecast.topolo.app",
4104
- forms: "https://forms.topolo.app",
4105
- home: "https://home.topolo.app",
4106
- insights: "https://insights.topolo.app",
4107
- inventory: "https://inventory.topolo.app",
4108
- learn: "https://learn.topolo.app",
4109
- localize: "https://localize.topolo.app",
4110
- mail: "https://mail.topolo.app",
4111
- mdm: "https://mdm.topolo.app",
4112
- messages: "https://messages.topolo.app",
4113
- nexus: "https://nexus.topolo.app",
4114
- notify: "https://notify.topolo.app",
4115
- observability_watch: "https://observability-watch.topolo.app",
4116
- one: "https://www.topolo.app",
4117
- p2p: "https://p2p.topolo.app",
4118
- pay: "https://pay.topolo.app",
4119
- people: "https://people.topolo.app",
4120
- "quro.api": "https://api.ol0.me",
4121
- "quro.redirect": "https://ol0.me",
4122
- roadmapper: "https://roadmapper.topolo.app",
4123
- sign: "https://sign.topolo.app",
4124
- social_studio: "https://studio.topolo.app",
4125
- socialize: "https://socialize.topolo.app",
4126
- spaces: "https://spaces.topolo.app",
4127
- status: "https://status.topolo.app",
4128
- success: "https://success.topolo.app",
4129
- support: "https://support.topolo.app",
4130
- survey: "https://survey.topolo.app",
4131
- voice: "https://voice.topolo.app",
4132
- web: "https://web.topolo.app"
4184
+ developers: "https://developers.topolo.app"
4133
4185
  };
4134
4186
  var DEFAULT_APP_URLS2 = APP_API_URLS2;
4135
4187
  function resolveServiceUrl2(service, overrides) {
@@ -6523,12 +6575,6 @@ function normalizeContainerAppId(value, surfaceModel) {
6523
6575
  function normalizeApplicationId(application) {
6524
6576
  const raw = application.trim().toLowerCase();
6525
6577
  const normalized = raw.replace(/-/g, "_");
6526
- if (Object.prototype.hasOwnProperty.call(APPLICATIONS, raw)) {
6527
- return raw;
6528
- }
6529
- if (Object.prototype.hasOwnProperty.call(APPLICATIONS, normalized)) {
6530
- return normalized;
6531
- }
6532
6578
  if (/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(raw) || /^[a-z0-9](?:[a-z0-9_]*[a-z0-9])?$/.test(raw)) {
6533
6579
  return normalized;
6534
6580
  }
@@ -9914,7 +9960,7 @@ function applicationScaffoldPayload(application, options = {}) {
9914
9960
  const requestedId = normalizeApplicationId(application);
9915
9961
  const id = target === "platform" ? normalizeFirstPartyApplicationId(requestedId) : requestedId;
9916
9962
  const slug = toSlug(id);
9917
- const catalogApplication = APPLICATIONS[id];
9963
+ const catalogApplication = options.catalogApplication ?? null;
9918
9964
  const browser = options.browser !== false;
9919
9965
  const api = options.api ?? target === "platform";
9920
9966
  const audience = normalizeAudience(
@@ -11550,7 +11596,6 @@ function registerApplicationReconcileCommand(parent, ownerType, dependencies = {
11550
11596
  }
11551
11597
 
11552
11598
  // src/commands/apps.ts
11553
- var APPLICATION_IDS = Object.keys(APPLICATIONS).sort();
11554
11599
  var CLOUDCONTROL_LOCAL_APPLICATION = {
11555
11600
  id: "cloudcontrol",
11556
11601
  appDir: "TopoloCloudControl",
@@ -11560,6 +11605,21 @@ var CLOUDCONTROL_LOCAL_APPLICATION = {
11560
11605
  services: [],
11561
11606
  deployTargets: []
11562
11607
  };
11608
+ async function directoryClient() {
11609
+ try {
11610
+ const topolo = await buildClient();
11611
+ return topolo ? topolo.client : null;
11612
+ } catch {
11613
+ return null;
11614
+ }
11615
+ }
11616
+ async function resolveScaffoldCatalogApplication(application) {
11617
+ try {
11618
+ return await resolveApplication(application, await directoryClient());
11619
+ } catch {
11620
+ return null;
11621
+ }
11622
+ }
11563
11623
  function registerAppsCommand(program2) {
11564
11624
  const apps = program2.command("apps").description("Search Topolo platform applications available to the current credential").option("-q, --query <query>", "Filter by app id, slug, or name").option("--cursor <cursor>", "Continuation cursor from the previous page").option("--limit <limit>", "Page size (1-100)", "25").option("--json", "Output JSON", true).option("--no-json", "Output human-readable table").action(async (opts) => {
11565
11625
  const mode = resolveOutputMode(opts.json);
@@ -11597,10 +11657,10 @@ function registerAppsCommand(program2) {
11597
11657
  });
11598
11658
  apps.command("requirements [application]").description(
11599
11659
  "Show the versioned Topolo application-build requirements, optionally filtered to one app."
11600
- ).option("--json", "Output JSON", true).option("--no-json", "Output human-readable details").action((application, opts) => {
11660
+ ).option("--json", "Output JSON", true).option("--no-json", "Output human-readable details").action(async (application, opts) => {
11601
11661
  const mode = resolveOutputMode(opts.json);
11602
11662
  try {
11603
- const payload = applicationRequirementsPayload(application);
11663
+ const payload = await applicationRequirementsPayload(application, await directoryClient());
11604
11664
  emit(payload, mode, () => formatRequirements(payload));
11605
11665
  } catch (err) {
11606
11666
  fail(err, mode);
@@ -11611,12 +11671,13 @@ function registerAppsCommand(program2) {
11611
11671
  ).option("--json", "Output JSON", true).option("--no-json", "Output human-readable table").option("--local", "Inspect the local Topolo checkout for filesystem-backed evidence").option("--repo-root <path>", "Topolo checkout root to inspect when --local is set").option(
11612
11672
  "--fail-on <status>",
11613
11673
  "Exit non-zero when audit has findings at this severity or worse: missing, needs_review, partial"
11614
- ).action((application, opts) => {
11674
+ ).action(async (application, opts) => {
11615
11675
  const mode = resolveOutputMode(opts.json);
11616
11676
  try {
11617
- const payload = applicationAuditPayload(application, {
11677
+ const payload = await applicationAuditPayload(application, {
11618
11678
  local: opts.local,
11619
- repoRoot: opts.repoRoot
11679
+ repoRoot: opts.repoRoot,
11680
+ client: await directoryClient()
11620
11681
  });
11621
11682
  const gate = opts.failOn ? evaluateApplicationAuditGate(payload, opts.failOn) : null;
11622
11683
  const output2 = gate ? { ...payload, conformanceGate: gate } : payload;
@@ -11636,10 +11697,13 @@ function registerAppsCommand(program2) {
11636
11697
  });
11637
11698
  apps.command("record-evidence <application>").description(
11638
11699
  "Stamp <repo>/.topolo/evidence.json with the latest CI gate results so the audit can flip verification-gates / observability-and-audit / canonical-docs from partial to met when the recorded run is fresh (< 24h)."
11639
- ).option("--json", "Output JSON", true).option("--no-json", "Output human-readable summary").option("--app-root <path>", "Path to the application repo root (defaults to cwd)").option("--build", "Mark the latest build as successful").option("--typecheck", "Mark the latest typecheck as successful").option("--test", "Mark the latest test run as successful").option("--docs-validate", "Mark the latest TopoloDocs npm run validate as successful").option("--smoke <url>", "Mark the latest live smoke as successful against this URL").option("--commit <sha>", "Override the commit hash (defaults to git HEAD)").action((application, opts) => {
11700
+ ).option("--json", "Output JSON", true).option("--no-json", "Output human-readable summary").option("--app-root <path>", "Path to the application repo root (defaults to cwd)").option("--build", "Mark the latest build as successful").option("--typecheck", "Mark the latest typecheck as successful").option("--test", "Mark the latest test run as successful").option("--docs-validate", "Mark the latest TopoloDocs npm run validate as successful").option("--smoke <url>", "Mark the latest live smoke as successful against this URL").option("--commit <sha>", "Override the commit hash (defaults to git HEAD)").action(async (application, opts) => {
11640
11701
  const mode = resolveOutputMode(opts.json);
11641
11702
  try {
11642
- const payload = recordApplicationEvidence(application, opts);
11703
+ const payload = await recordApplicationEvidence(application, {
11704
+ ...opts,
11705
+ client: await directoryClient()
11706
+ });
11643
11707
  emit(payload, mode, () => formatEvidence(payload));
11644
11708
  } catch (err) {
11645
11709
  fail(err, mode);
@@ -11661,6 +11725,7 @@ function registerAppsCommand(program2) {
11661
11725
  try {
11662
11726
  const api = resolveScaffoldApiOption(opts.api, opts.withApi);
11663
11727
  const payload = applicationScaffoldPayload(application, {
11728
+ catalogApplication: await resolveScaffoldCatalogApplication(application),
11664
11729
  appDir: opts.appDir,
11665
11730
  name: opts.name,
11666
11731
  packageName: opts.packageName,
@@ -11722,14 +11787,11 @@ function parsePageSize2(value) {
11722
11787
  }
11723
11788
  return parsed;
11724
11789
  }
11725
- function resolveApplication(application) {
11726
- const id = application.trim().toLowerCase();
11727
- if (!APPLICATION_IDS.includes(id)) {
11728
- throw new Error(`Unknown application "${application}". ${formatKnownValues(APPLICATION_IDS, "applications")}`);
11729
- }
11730
- return APPLICATIONS[id];
11790
+ async function resolveApplication(application, client = null) {
11791
+ const resolved = await resolveApplicationDirectoryEntry(client, application);
11792
+ return resolved.application;
11731
11793
  }
11732
- function applicationRequirementsPayload(application) {
11794
+ async function applicationRequirementsPayload(application, client = null) {
11733
11795
  if (!application) {
11734
11796
  return {
11735
11797
  version: APPLICATION_REQUIREMENTS_VERSION,
@@ -11738,7 +11800,7 @@ function applicationRequirementsPayload(application) {
11738
11800
  requirements: [...APPLICATION_REQUIREMENTS]
11739
11801
  };
11740
11802
  }
11741
- const app = resolveApplication(application);
11803
+ const app = await resolveApplication(application, client);
11742
11804
  return {
11743
11805
  version: APPLICATION_REQUIREMENTS_VERSION,
11744
11806
  application: app,
@@ -11746,18 +11808,21 @@ function applicationRequirementsPayload(application) {
11746
11808
  requirements: requirementsForApplication(app)
11747
11809
  };
11748
11810
  }
11749
- function applicationAuditPayload(application, options = {}) {
11811
+ async function applicationAuditPayload(application, options = {}) {
11812
+ const client = options.client ?? null;
11750
11813
  const requestedId = application?.trim().toLowerCase();
11751
11814
  const report = requestedId === "cloudcontrol" && options.local ? {
11752
11815
  version: APPLICATION_REQUIREMENTS_VERSION,
11753
11816
  applications: [auditApplicationRequirements(CLOUDCONTROL_LOCAL_APPLICATION)],
11754
11817
  migrationQueue: []
11755
- } : application ? auditAllApplicationRequirements([resolveApplication(application).id]) : auditAllApplicationRequirements();
11818
+ } : application ? auditApplicationEntries([await resolveApplication(application, client)]) : auditApplicationEntries(
11819
+ (await listApplicationDirectory(client)).applications.map((app) => app.application)
11820
+ );
11756
11821
  if (!options.local) return report;
11757
11822
  return enrichApplicationAuditWithLocalEvidence(report, { repoRoot: options.repoRoot });
11758
11823
  }
11759
- function recordApplicationEvidence(application, options = {}) {
11760
- const appId = resolveApplication(application).id;
11824
+ async function recordApplicationEvidence(application, options = {}) {
11825
+ const appId = (await resolveApplication(application, options.client ?? null)).id;
11761
11826
  const root = path6.resolve(options.appRoot ?? process.cwd());
11762
11827
  if (!existsSync4(root)) {
11763
11828
  throw new Error(`Application root does not exist: ${root}`);
@@ -11888,22 +11953,7 @@ function applicationUrl(application) {
11888
11953
  return application.apiBaseUrl ?? application.launchUrl ?? application.productionUrl ?? null;
11889
11954
  }
11890
11955
  function displayCatalogId(entry) {
11891
- for (const value of [entry.slug, entry.name, entry.appId]) {
11892
- if (typeof value !== "string" || !value.trim()) continue;
11893
- const candidates = catalogIdCandidates(value);
11894
- const withoutTopolo = candidates.find((candidate) => !candidate.startsWith("topolo-"));
11895
- if (withoutTopolo) return withoutTopolo;
11896
- if (candidates[0]) return candidates[0];
11897
- }
11898
- return entry.appId;
11899
- }
11900
- function catalogIdCandidates(value) {
11901
- const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
11902
- const withoutTopolo = normalized.startsWith("topolo-") ? normalized.slice("topolo-".length) : normalized;
11903
- return [.../* @__PURE__ */ new Set([
11904
- normalized,
11905
- withoutTopolo
11906
- ])].filter(Boolean);
11956
+ return friendlyAppId(entry);
11907
11957
  }
11908
11958
  function formatRequirements(payload) {
11909
11959
  const lines = [
@@ -12067,12 +12117,6 @@ function normalizeFailOn(value) {
12067
12117
  }
12068
12118
  throw new Error("Invalid --fail-on value. Use missing, needs_review, or partial.");
12069
12119
  }
12070
- function formatKnownValues(values, label) {
12071
- const sorted = [...values].sort();
12072
- const preview = sorted.slice(0, 25).join(", ");
12073
- const suffix = sorted.length > 25 ? `, ... +${sorted.length - 25} more` : "";
12074
- return `Run discovery for the full ${label} list. Known snapshot sample: ${preview}${suffix}`;
12075
- }
12076
12120
  function statusesAtOrWorse(threshold) {
12077
12121
  if (threshold === "missing") return ["missing"];
12078
12122
  if (threshold === "needs_review") return ["missing", "needs_review"];
@@ -12274,6 +12318,7 @@ function registerPlatformCommand(program2) {
12274
12318
  }
12275
12319
  const api = resolveScaffoldApiOption(opts.api, opts.withApi);
12276
12320
  const payload = applicationScaffoldPayload(application, {
12321
+ catalogApplication: await resolveScaffoldCatalogApplication(application),
12277
12322
  appDir: opts.appDir,
12278
12323
  name: opts.name,
12279
12324
  packageName: opts.packageName,
@@ -12525,15 +12570,7 @@ function isStagingUrl(value) {
12525
12570
  return url.includes(".stg.topolo.us") || url.includes("localhost") || url.includes("127.0.0.1") || url.includes("topolo-staging");
12526
12571
  }
12527
12572
  function displayAppId(entry) {
12528
- for (const value of [entry.slug, entry.name, entry.appId]) {
12529
- if (typeof value !== "string" || !value.trim()) continue;
12530
- for (const candidate of appIdCandidates(value)) {
12531
- if (Object.prototype.hasOwnProperty.call(DEFAULT_APP_URLS, candidate)) {
12532
- return candidate;
12533
- }
12534
- }
12535
- }
12536
- return appIdCandidates(entry.slug || entry.appId)[0] || entry.appId;
12573
+ return friendlyAppId(entry);
12537
12574
  }
12538
12575
  function defaultServiceUrl(id, entry) {
12539
12576
  return resolveCatalogServiceUrl(entry, { serviceKey: id });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@topolo/cli",
3
- "version": "0.6.10",
4
- "topoloPublishedVersion": "0.6.10",
3
+ "version": "0.7.0",
4
+ "topoloPublishedVersion": "0.7.0",
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": {
@@ -4,7 +4,7 @@ This file teaches an agent how to interact with the Topolo platform via the `top
4
4
 
5
5
  ## What the platform is
6
6
 
7
- Topolo is a multi-app SaaS platform. The CLI and MCP server both use `@topolo/sdk`; bundled app IDs come from the generated registry, and newly registered API/technical services can be resolved from the live Auth catalog.
7
+ Topolo is a multi-app SaaS platform. The CLI and MCP server both use `@topolo/sdk`; every application resolves from the live credential-scoped registry, so newly registered apps and API/technical services work immediately — there is no bundled application catalog to rely on or wait for.
8
8
 
9
9
  - Use `topolo apps --json` or the MCP `topolo_search_applications` tool to discover platform applications, including browser-only Worker apps.
10
10
  - Use `topolo apps requirements <application_id> --json` or the MCP `topolo_list_application_requirements` tool before creating or expanding a Topolo app.
@@ -12,7 +12,7 @@ Topolo is a multi-app SaaS platform. The CLI and MCP server both use `@topolo/sd
12
12
  - Use `topolo services --json` or the MCP `topolo_search_applications` tool to discover callable app ids and effective URLs.
13
13
  - Use `topolo actions --service <app> --json` or MCP `topolo_search_actions` to discover callable operations granted to the current credential; invoke automatic reads with `topolo_read_action` and confirmation-gated operations with `topolo_call_action`.
14
14
  - Use `topolo actions capabilities`, `actions examples`, `actions validate`, and `actions plan` (or their MCP equivalents) to obtain schemas, examples, verification, and rollback before execution.
15
- - The generic `api` command and MCP `topolo_api_call` tool can reach bundled SDK services and live Auth-catalog API/technical services when no action contract exists yet.
15
+ - The generic `api` command and MCP `topolo_api_call` tool can reach any live Auth-catalog application or API/technical service when no action contract exists yet; discover ids with `topolo apps --json` first.
16
16
 
17
17
  Every call is scoped to the organization embedded in the credential. There is no `--org` flag anywhere — attempting to target another org will fail.
18
18