@vertesia/common 1.5.0-dev.20260714.072725Z → 1.5.0-dev.20260717.131047Z

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": "@vertesia/common",
3
- "version": "1.5.0-dev.20260714.072725Z",
3
+ "version": "1.5.0-dev.20260717.131047Z",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -17,7 +17,7 @@
17
17
  }
18
18
  },
19
19
  "devDependencies": {
20
- "rolldown": "1.1.3",
20
+ "rolldown": "1.1.4",
21
21
  "typescript": "^6.0.3",
22
22
  "vitest": "^4.1.9",
23
23
  "@vertesia/tsconfig": "0.1.0"
@@ -39,6 +39,7 @@
39
39
  "ai",
40
40
  "typescript"
41
41
  ],
42
+ "gitHead": "8aaad228827b2927db8e6aa75b27bfac90fec36f",
42
43
  "scripts": {
43
44
  "lint": "biome lint src",
44
45
  "test": "vitest run",
package/src/apikey.ts CHANGED
@@ -145,6 +145,7 @@ export interface AuthTokenPayload {
145
145
  studio: string;
146
146
  store: string;
147
147
  token?: string;
148
+ git?: string;
148
149
  };
149
150
 
150
151
  iss: string; //issuer
package/src/apps.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { JSONObject, JSONSchema, ToolDefinition } from '@llumiverse/common';
2
+ import type { AppDashboardDefinition } from './data-platform.js';
2
3
  import type { CatalogInteractionRef } from './interaction.js';
3
4
  import type { DSLActivityOptions, InCodeProcessDefinition, InCodeTypeDefinition } from './store/index.js';
4
5
 
@@ -382,9 +383,301 @@ export interface RemoteActivityDefinition {
382
383
  options?: DSLActivityOptions;
383
384
  }
384
385
 
385
- export type AppCapabilities = 'ui' | 'tools' | 'interactions' | 'types' | 'processes' | 'templates';
386
+ export type AppCapabilities = 'ui' | 'tools' | 'interactions' | 'types' | 'processes' | 'templates' | 'dashboards';
387
+
388
+ /**
389
+ * Canonical runtime list of {@link AppCapabilities} — the app capabilities Studio
390
+ * renders/supports. Co-located with the type so TypeScript rejects any drift between
391
+ * the two. Consumers (publish manifest derivation, etc.) must use this rather than
392
+ * re-listing the values.
393
+ */
394
+ export const APP_CAPABILITIES: readonly AppCapabilities[] = [
395
+ 'ui',
396
+ 'tools',
397
+ 'interactions',
398
+ 'types',
399
+ 'processes',
400
+ 'templates',
401
+ 'dashboards',
402
+ ];
403
+
404
+ /**
405
+ * Header carrying the app version a generated-app UI is running, so studio/zeno resolve app-owned
406
+ * capability refs (`app:<app>:...`) against that version (candidate testing) instead of current.
407
+ * Resolution-time only; never persisted. Set by the generated app template via client.withAppVersion.
408
+ */
409
+ export const APP_VERSION_HEADER = 'x-vertesia-app-version';
410
+ /**
411
+ * The platform-artifact types an app build can be required to create. A finer-grained
412
+ * counterpart to {@link AppCapabilities}: a single `interactions` capability may comprise
413
+ * several `interaction` artifacts plus `agent`, `activity`, and `tool` artifacts that
414
+ * {@link AppCapabilities} folds together. Used by the App Solution Architect manifest and
415
+ * the publish-time capability gate.
416
+ */
417
+ export type AppArtifactType =
418
+ | 'interaction'
419
+ | 'agent'
420
+ | 'type'
421
+ | 'process'
422
+ | 'template'
423
+ | 'dashboard'
424
+ | 'activity'
425
+ | 'tool';
426
+
427
+ export const APP_ARTIFACT_TYPES: readonly AppArtifactType[] = [
428
+ 'interaction',
429
+ 'agent',
430
+ 'type',
431
+ 'process',
432
+ 'template',
433
+ 'dashboard',
434
+ 'activity',
435
+ 'tool',
436
+ ];
437
+
438
+ /**
439
+ * A single platform artifact the App Solution Architect requires the build to create.
440
+ * `id` is the app-owned in-code id the implementation must register and reference
441
+ * (e.g. `app:<name>:main:extract-item` for interactions/agents, `app:<name>:<type>` for
442
+ * types, `app:<name>:<process>` for processes).
443
+ */
444
+ /**
445
+ * Build progress for one artifact, maintained by the developer agent as a living checklist:
446
+ * - `pending` — defined by the architect, not yet built.
447
+ * - `built` — registered in the package, not yet successfully exercised.
448
+ * - `done` — built AND successfully exercised against real data.
449
+ * This is the agent's self-reported claim for tracking/handoff; the capability gate verifies
450
+ * the truth independently via package registration + run/data telemetry and does not trust it.
451
+ */
452
+ export type AppArtifactStatus = 'pending' | 'built' | 'done';
453
+
454
+ export const APP_ARTIFACT_STATUSES: readonly AppArtifactStatus[] = ['pending', 'built', 'done'];
455
+
456
+ export interface AppPlannedArtifact {
457
+ /** App-owned in-code id the build must register and reference. */
458
+ id: string;
459
+ type: AppArtifactType;
460
+ /** Short human label. */
461
+ name?: string;
462
+ /** Why this artifact exists / what it does — carried into the build checklist. */
463
+ purpose?: string;
464
+ /**
465
+ * When false, the artifact is planned but optional: the capability gate warns rather
466
+ * than blocks if it is missing or never exercised. Defaults to required (true).
467
+ */
468
+ required?: boolean;
469
+ /** Build progress, updated by the developer agent. Defaults to `pending`. */
470
+ status?: AppArtifactStatus;
471
+ }
472
+
473
+ /**
474
+ * Structured result the App Solution Architect emits alongside its prose artifacts — the
475
+ * machine-readable contract for the build. The implementation MUST create and successfully
476
+ * exercise every required artifact before preview/publish. Persisted into the app repo as
477
+ * {@link APP_CAPABILITY_MANIFEST_PATH} so it survives across runs and the publish-time
478
+ * capability gate can verify against it deterministically. If the builder finds the plan
479
+ * wrong or insufficient, the orchestrator relaunches the architect to revise the manifest;
480
+ * the gate always checks against the latest committed copy.
481
+ */
482
+ export interface AppCapabilityManifest {
483
+ /** Artifact-storage ref to the prose architecture spec (e.g. the architecture `.md`). */
484
+ spec_artifact: string;
485
+ /** Platform artifacts the build must create. */
486
+ artifacts: AppPlannedArtifact[];
487
+ /**
488
+ * Monotonic revision, starting at 1, bumped each time the architect evolves the manifest for
489
+ * the SAME app on a later iteration (read the committed manifest, preserve untouched artifacts,
490
+ * add/modify/remove, then bump). Lets downstream agents tell which contract they are building to.
491
+ */
492
+ revision?: number;
493
+ /**
494
+ * Newest-first change notes, one entry per revision (what was added/modified/removed and why).
495
+ * How manifest changes are communicated to downstream agents across iterations.
496
+ */
497
+ changelog?: string[];
498
+ /** Optional free-form notes the architect wants the builder to honor. */
499
+ notes?: string;
500
+ }
501
+
502
+ /** Repo-relative path the capability manifest is committed to, read by the publish gate. */
503
+ export const APP_CAPABILITY_MANIFEST_PATH = 'docs/app-capability-manifest.json';
504
+
386
505
  export type AppAvailableIn = 'app_portal' | 'composite_app';
387
506
 
507
+ export type AppVersionKind = 'design' | 'preview' | 'published';
508
+ export type AppVersionState = 'ready' | 'failed' | 'expired';
509
+ export type AppVersionTarget = 'static' | 'service';
510
+ export type AppVersionGitRefType = 'branch' | 'tag' | 'commit' | 'detached';
511
+ export type AppBuildIntent = 'preview' | 'publish';
512
+ export type AppBuildTrigger = 'ui' | 'git_push' | 'agent' | 'api';
513
+
514
+ export interface AppVersionStorage {
515
+ tenant_id?: string;
516
+ app_prefix?: string;
517
+ artifacts_prefix?: string;
518
+ source_archive?: string;
519
+ source_git?: AppVersionGitSource;
520
+ build_prefix?: string;
521
+ manifest_path?: string;
522
+ service_archive?: string;
523
+ live_metadata_path?: string;
524
+ }
525
+
526
+ export interface AppVersionGitSource {
527
+ url?: string;
528
+ remote?: string;
529
+ /**
530
+ * The source ref that should be used to reproduce this version. For immutable
531
+ * app versions this is normally the tag created during preview/publish.
532
+ */
533
+ ref?: string;
534
+ ref_type?: AppVersionGitRefType;
535
+ branch?: string;
536
+ tag?: string;
537
+ commit?: string;
538
+ dirty?: boolean;
539
+ pushed?: boolean;
540
+ push_warning?: string;
541
+ }
542
+
543
+ export interface AppVersionUrls {
544
+ live_url?: string;
545
+ app_url?: string;
546
+ plugin_url?: string;
547
+ package_url?: string;
548
+ internal_preview_url?: string;
549
+ }
550
+
551
+ export interface AppVersionRecord {
552
+ id: string;
553
+ account: string;
554
+ project: string;
555
+ app?: string;
556
+ app_id: string;
557
+ app_name: string;
558
+ version_id: string;
559
+ kind: AppVersionKind;
560
+ state: AppVersionState;
561
+ active?: boolean;
562
+ target?: AppVersionTarget;
563
+ agent_run_id?: string;
564
+ sandbox_id?: string;
565
+ title?: string;
566
+ description?: string;
567
+ storage?: AppVersionStorage;
568
+ urls?: AppVersionUrls;
569
+ manifest?: Record<string, unknown>;
570
+ files?: string[];
571
+ file_count?: number;
572
+ source_file_count?: number;
573
+ screenshot_artifact?: string;
574
+ checks?: string[];
575
+ created_by?: string;
576
+ created_at: string;
577
+ updated_at: string;
578
+ published_at?: string;
579
+ checked_at?: string;
580
+ expires_at?: string;
581
+ }
582
+
583
+ export interface UpsertAppVersionRequest {
584
+ app?: string;
585
+ app_id: string;
586
+ app_name?: string;
587
+ version_id: string;
588
+ kind: AppVersionKind;
589
+ state?: AppVersionState;
590
+ active?: boolean;
591
+ target?: AppVersionTarget;
592
+ agent_run_id?: string;
593
+ sandbox_id?: string;
594
+ title?: string;
595
+ description?: string;
596
+ storage?: AppVersionStorage;
597
+ urls?: AppVersionUrls;
598
+ manifest?: Record<string, unknown>;
599
+ files?: string[];
600
+ file_count?: number;
601
+ source_file_count?: number;
602
+ screenshot_artifact?: string;
603
+ checks?: string[];
604
+ published_at?: string;
605
+ checked_at?: string;
606
+ expires_at?: string;
607
+ }
608
+
609
+ export interface AppVersionListQuery {
610
+ app_id?: string;
611
+ kind?: AppVersionKind;
612
+ include_expired?: boolean;
613
+ limit?: number;
614
+ }
615
+
616
+ export interface ActivateAppVersionResponse {
617
+ version: AppVersionRecord;
618
+ app?: AppManifest;
619
+ }
620
+
621
+ export interface StartAppBuildRequest {
622
+ /**
623
+ * Source branch, tag, or commit to build. When omitted, the app source
624
+ * configuration chooses the dev branch for previews and production branch
625
+ * for publishes.
626
+ */
627
+ source_ref?: string;
628
+ source_ref_type?: Extract<AppVersionGitRefType, 'branch' | 'tag' | 'commit'>;
629
+ intent?: AppBuildIntent;
630
+ trigger?: AppBuildTrigger;
631
+ target?: AppVersionTarget;
632
+ activate?: boolean;
633
+ title?: string;
634
+ description?: string;
635
+ }
636
+
637
+ export interface StartAppBuildResponse {
638
+ workflow_id: string;
639
+ run_id: string;
640
+ app_id: string;
641
+ intent: AppBuildIntent;
642
+ source_ref?: string;
643
+ source_ref_type?: Extract<AppVersionGitRefType, 'branch' | 'tag' | 'commit'>;
644
+ }
645
+
646
+ export interface AppBuildWorkflowInput extends StartAppBuildRequest {
647
+ app_id: string;
648
+ app_record_id?: string;
649
+ app_title?: string;
650
+ app_description?: string;
651
+ source_git_url?: string;
652
+ }
653
+
654
+ export interface AppBuildWorkflowResult {
655
+ app_id: string;
656
+ version_id: string;
657
+ kind: Extract<AppVersionKind, 'preview' | 'published'>;
658
+ state: AppVersionState;
659
+ source_git?: AppVersionGitSource;
660
+ urls?: AppVersionUrls;
661
+ file_count?: number;
662
+ }
663
+
664
+ export type AppBuildProgressStatus = 'queued' | 'resolving' | 'building' | 'completed' | 'failed';
665
+
666
+ export interface AppBuildProgress {
667
+ status: AppBuildProgressStatus;
668
+ step: string;
669
+ app_id?: string;
670
+ version_id?: string;
671
+ intent?: AppBuildIntent;
672
+ source_ref?: string;
673
+ source_ref_type?: Extract<AppVersionGitRefType, 'branch' | 'tag' | 'commit'>;
674
+ source_commit?: string;
675
+ file_count?: number;
676
+ app_url?: string;
677
+ error?: string;
678
+ updated_at: string;
679
+ }
680
+
388
681
  /**
389
682
  * Access control policy for an app installation.
390
683
  * Declares which access surfaces are gated by per-user ACEs.
@@ -445,6 +738,18 @@ export interface AppManifestData {
445
738
  */
446
739
  color?: string;
447
740
 
741
+ /**
742
+ * Optional preview screenshot for the app-management UI, captured by the builder during a
743
+ * build/QA run. Resolved client-side from the owning agent run's artifact storage, so it
744
+ * carries both the run id and the artifact path.
745
+ */
746
+ preview_screenshot?: {
747
+ /** Agent run id whose artifact storage holds the screenshot. */
748
+ agent_run_id: string;
749
+ /** Artifact path within that storage, e.g. "preview-checks/app-preview-<ts>.png". */
750
+ artifact: string;
751
+ };
752
+
448
753
  status: 'beta' | 'stable' | 'deprecated';
449
754
 
450
755
  /**
@@ -501,6 +806,8 @@ export interface AppManifestData {
501
806
  * - interactions
502
807
  * - types
503
808
  * - processes
809
+ * - templates
810
+ * - dashboards
504
811
  * - settings
505
812
  * - all (the default if no scope is provided)
506
813
  * You can also use comma-separated values to combine scopes (e.g. "ui,tools").
@@ -523,6 +830,13 @@ export interface AppManifestData {
523
830
  */
524
831
  version?: string;
525
832
 
833
+ /**
834
+ * Source repository configuration for apps generated and maintained through
835
+ * AppGen. Branches are mutable deployment lanes; immutable app versions
836
+ * record their exact source tag/commit in AppVersionRecord.storage.source_git.
837
+ */
838
+ source?: AppSourceConfig;
839
+
526
840
  /**
527
841
  * Free-form tags used for classification and filtering. Platform apps
528
842
  * carry `"system"` so UIs can skip install/uninstall/manage-permission
@@ -538,20 +852,16 @@ export interface AppManifestData {
538
852
  access_control?: AppAccessControl;
539
853
  }
540
854
 
541
- /**
542
- * Reserved deployment environment names that may never be used as endpoint
543
- * override keys. Reserving them prevents a manifest from hijacking auto-resolution
544
- * on a shared production studio-server (whose `Env.environment` is one of these).
545
- */
546
- const RESERVED_ENDPOINT_OVERRIDE_ENVS = new Set(['production', 'preview', 'staging']);
855
+ export interface AppGitSourceConfig {
856
+ url?: string;
857
+ default_branch?: string;
858
+ production_branch?: string;
859
+ development_branch?: string;
860
+ }
547
861
 
548
- /**
549
- * Returns true if the given environment name is allowed as an endpoint override key.
550
- * Any non-empty name is accepted except the reserved shared-deployment names.
551
- */
552
- export function isValidEndpointOverrideEnv(envName: string): boolean {
553
- if (!envName) return false;
554
- return !RESERVED_ENDPOINT_OVERRIDE_ENVS.has(envName.toLowerCase());
862
+ export interface AppSourceConfig {
863
+ kind: 'git';
864
+ git?: AppGitSourceConfig;
555
865
  }
556
866
 
557
867
  /**
@@ -569,6 +879,10 @@ export interface Endpoints {
569
879
  token?: string;
570
880
  /** The browser-facing Studio UI (composable-ui) base URL */
571
881
  ui?: string;
882
+ /** The Smart HTTP app source git server base URL */
883
+ git?: string;
884
+ /** The appgen app-gateway base URL (serves published app bundles + their `/api` runtime). */
885
+ gateway?: string;
572
886
  }
573
887
 
574
888
  /**
@@ -577,7 +891,7 @@ export interface Endpoints {
577
891
  * with the unresolved placeholder visible, rather than silently pointing nowhere).
578
892
  * Trailing slashes on replacement values are stripped to avoid `//api/...` joins.
579
893
  */
580
- export function substituteEndpoints(url: string, endpoints?: Endpoints): string {
894
+ function substituteEndpoints(url: string, endpoints?: Endpoints): string {
581
895
  if (!url || !endpoints) return url;
582
896
  return url.replace(/\{\{\s*(\w+)\s*\}\}/g, (match, key: string) => {
583
897
  const value = (endpoints as Record<string, string | undefined>)[key];
@@ -594,72 +908,55 @@ function trimTrailingSlashes(value: string): string {
594
908
  return end === value.length ? value : value.slice(0, end);
595
909
  }
596
910
 
597
- /**
598
- * Resolves the effective endpoint for an app.
599
- *
600
- * Order of resolution:
601
- * 1. If `requestedOverride` matches an `endpoint_overrides` key, use that URL
602
- * (caller must verify the user is allowed to use the override).
603
- * 2. Else if `envName` matches an `endpoint_overrides` key, use that URL
604
- * (auto-resolution from the studio-server's deployment env).
605
- * 3. Otherwise use the main `endpoint`.
606
- * 4. Apply `{{var}}` substitution using `vars`.
607
- */
608
- export function resolveAppEndpoint(
609
- manifest: Pick<AppManifestData, 'endpoint' | 'endpoint_overrides'>,
610
- envName?: string,
611
- vars?: Endpoints,
612
- requestedOverride?: string,
613
- ): string | undefined {
614
- let raw: string | undefined;
615
- if (
616
- requestedOverride &&
617
- manifest.endpoint_overrides?.[requestedOverride] &&
618
- isValidEndpointOverrideEnv(requestedOverride)
619
- ) {
620
- raw = manifest.endpoint_overrides[requestedOverride];
621
- } else if (envName && manifest.endpoint_overrides?.[envName] && isValidEndpointOverrideEnv(envName)) {
622
- raw = manifest.endpoint_overrides[envName];
623
- } else {
624
- raw = manifest.endpoint;
625
- }
626
- return raw ? substituteEndpoints(raw, vars) : raw;
911
+ /** One entry in an app git-repo directory listing (see {@link AppRepoTree}). */
912
+ export interface AppRepoTreeEntry {
913
+ /** File or directory name (last path segment). */
914
+ name: string;
915
+ /** Path relative to the repo root. */
916
+ path: string;
917
+ /** Whether the entry is a file (`blob`) or a directory (`tree`). */
918
+ type: 'blob' | 'tree';
627
919
  }
628
920
 
629
- /**
630
- * Resolves all URL placeholders in a manifest in place (both `endpoint` and
631
- * `tool_collections[].url`). Intended for server-side serialization — clients and
632
- * downstream workers receive already-substituted URLs so they don't need to know
633
- * about deployment-time vars.
634
- *
635
- * Mutates the manifest rather than returning a copy so it works cleanly with
636
- * Mongoose populated subdocs.
637
- */
638
- export function resolveManifestUrls(
639
- manifest: Partial<AppManifestData> | null | undefined,
640
- envName?: string,
641
- vars?: Endpoints,
642
- requestedOverride?: string,
643
- ): void {
644
- if (!manifest) return;
645
-
646
- if (manifest.endpoint) {
647
- const resolved = resolveAppEndpoint(manifest, envName, vars, requestedOverride);
648
- if (resolved && resolved !== manifest.endpoint) {
649
- manifest.endpoint = resolved;
650
- }
651
- }
921
+ /** A non-recursive listing of an app git repo directory at a given ref. */
922
+ export interface AppRepoTree {
923
+ /** The ref the listing was read at (empty/undefined = default branch / HEAD). */
924
+ ref?: string;
925
+ /** The directory prefix that was listed (empty = repo root). */
926
+ prefix?: string;
927
+ entries: AppRepoTreeEntry[];
928
+ }
652
929
 
653
- const toolCollections = manifest.tool_collections as ToolCollectionObject[] | undefined;
654
- if (toolCollections && Array.isArray(toolCollections)) {
655
- for (let i = 0; i < toolCollections.length; i++) {
656
- const item = toolCollections[i];
657
- if (item && typeof item === 'object' && item.url) {
658
- const sub = substituteEndpoints(item.url, vars);
659
- if (sub !== item.url) item.url = sub;
660
- }
661
- }
662
- }
930
+ /** The content of a single file read from an app git repo at a given ref. */
931
+ export interface AppRepoFile {
932
+ /** Path relative to the repo root. */
933
+ path: string;
934
+ /** The ref the file was read at (empty/undefined = default branch / HEAD). */
935
+ ref?: string;
936
+ /** UTF-8 file content. */
937
+ content: string;
938
+ }
939
+
940
+ /** A branch or tag in an app git repo, resolved to its latest commit. */
941
+ export interface AppRepoRef {
942
+ /** Short ref name (e.g. `main`, `v1.0.0`). */
943
+ name: string;
944
+ /** Commit hash the ref points at (annotated tags are peeled to their commit). */
945
+ commit: string;
946
+ /** First line of the commit message, when available. */
947
+ commit_subject?: string;
948
+ /** Commit date as an ISO-8601 string, when available. */
949
+ commit_date?: string;
950
+ /** Commit author name, when available. */
951
+ commit_author?: string;
952
+ }
953
+
954
+ /** The branches and tags of an app git repo (see {@link AppRepoRef}). */
955
+ export interface AppRepoRefs {
956
+ /** The repository's default branch (HEAD target), when resolvable. */
957
+ default_branch?: string;
958
+ branches: AppRepoRef[];
959
+ tags: AppRepoRef[];
663
960
  }
664
961
 
665
962
  export type AppPackageScope =
@@ -669,10 +966,30 @@ export type AppPackageScope =
669
966
  | 'types'
670
967
  | 'processes'
671
968
  | 'templates'
969
+ | 'dashboards'
672
970
  | 'settings'
673
971
  | 'widgets'
674
972
  | 'activities'
675
973
  | 'all';
974
+
975
+ /**
976
+ * Canonical runtime list of {@link AppPackageScope} — every package scope, including the
977
+ * catch-all `'all'`. Co-located with the type so TypeScript rejects drift. Consumers (the
978
+ * /package?scope= parser, the inspection report) must use this rather than re-listing.
979
+ */
980
+ export const APP_PACKAGE_SCOPES: readonly AppPackageScope[] = [
981
+ 'ui',
982
+ 'tools',
983
+ 'interactions',
984
+ 'types',
985
+ 'processes',
986
+ 'templates',
987
+ 'dashboards',
988
+ 'settings',
989
+ 'widgets',
990
+ 'activities',
991
+ 'all',
992
+ ];
676
993
  export interface AppPackage {
677
994
  /**
678
995
  * The UI configuration of the app
@@ -712,6 +1029,11 @@ export interface AppPackage {
712
1029
  */
713
1030
  templates?: RenderingTemplateDefinitionRef[];
714
1031
 
1032
+ /**
1033
+ * Dashboards provided by the app.
1034
+ */
1035
+ dashboards?: AppDashboardDefinition[];
1036
+
715
1037
  /**
716
1038
  * Widgets provided by the app.
717
1039
  */
@@ -730,6 +1052,61 @@ export interface AppPackage {
730
1052
  settings_schema?: JSONSchema;
731
1053
  }
732
1054
 
1055
+ /**
1056
+ * A single diagnostic produced while inspecting an app's registration state.
1057
+ */
1058
+ export interface AppInspectionIssue {
1059
+ severity: 'error' | 'warning';
1060
+ /** The capability this issue relates to, when applicable (e.g. 'types'). */
1061
+ capability?: AppPackageScope;
1062
+ /** Stable machine code, e.g. 'capability_declared_but_empty', 'endpoint_unreachable', 'not_installed'. */
1063
+ code: string;
1064
+ /** Human-readable explanation, safe to surface to the model and the UI. */
1065
+ message: string;
1066
+ }
1067
+
1068
+ /**
1069
+ * Per-capability report of what an app's published package actually exposes,
1070
+ * compared against what its manifest declares.
1071
+ */
1072
+ export interface AppInspectionCapabilityReport {
1073
+ capability: AppPackageScope;
1074
+ /** True when the manifest's `capabilities` array declares this capability. */
1075
+ declared: boolean;
1076
+ /** The local ids the published package actually serves for this capability. */
1077
+ exposed_ids: string[];
1078
+ /** Convenience count of `exposed_ids`. */
1079
+ exposed_count: number;
1080
+ }
1081
+
1082
+ /**
1083
+ * Result of inspecting an app's registration: the resolved manifest state, what
1084
+ * the published package actually exposes per capability, and diagnostics. This
1085
+ * is the ground truth used by the `app_inspect_registration` agent tool and the
1086
+ * Build › App inspection UI to verify what is registered vs declared, instead of
1087
+ * inferring it from failed object/import calls.
1088
+ */
1089
+ export interface AppInspectionResult {
1090
+ app_id: string;
1091
+ name: string;
1092
+ version?: string;
1093
+ /** The resolved package endpoint for the current environment, if any. */
1094
+ endpoint?: string;
1095
+ /** True when the package endpoint responded to the capability probe. */
1096
+ endpoint_reachable: boolean;
1097
+ /** True when the app is installed in the current project. */
1098
+ installed: boolean;
1099
+ access_control?: string;
1100
+ /** The capabilities declared on the manifest. */
1101
+ capabilities: AppPackageScope[];
1102
+ /** What the published package exposes, per capability. */
1103
+ package: AppInspectionCapabilityReport[];
1104
+ /** Diagnostics — errors and warnings about the registration state. */
1105
+ issues: AppInspectionIssue[];
1106
+ /** Populated when the package probe itself failed (endpoint error/unreachable). */
1107
+ probe_error?: string;
1108
+ }
1109
+
733
1110
  export interface AppWidgetInfo {
734
1111
  collection: string;
735
1112
  skill: string;
@@ -775,6 +1152,7 @@ export interface AppManifestSource {
775
1152
  git: {
776
1153
  url: string;
777
1154
  default_branch?: string;
1155
+ production_branch?: string;
778
1156
  development_branch?: string;
779
1157
  };
780
1158
  }
@@ -1322,3 +1700,20 @@ export interface ValidateUrlRequest {
1322
1700
  export interface ValidateUrlResponse {
1323
1701
  valid: true;
1324
1702
  }
1703
+
1704
+ /**
1705
+ * Result of DELETE /api/v1/apps/:id. With `?confirm=true` the cascade runs and
1706
+ * `deleted: true` is set; without it the endpoint returns a dry-run summary so
1707
+ * the UI can show what would be removed.
1708
+ */
1709
+ export interface AppDeleteSummary {
1710
+ confirmed: boolean;
1711
+ app_id: string;
1712
+ app_name: string;
1713
+ versions: number;
1714
+ installations: number;
1715
+ storage_prefix: string;
1716
+ git_repo_url?: string;
1717
+ deleted: boolean;
1718
+ warnings: string[];
1719
+ }