@ngis/plugin-sdk 0.4.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/LICENSE +13 -0
- package/README.md +31 -0
- package/dist/index.cjs +76 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.mjs +102 -0
- package/dist/src/api/analysis.d.ts +140 -0
- package/dist/src/api/resources.d.ts +530 -0
- package/dist/src/api/scenes.d.ts +251 -0
- package/dist/src/api/users.d.ts +22 -0
- package/dist/src/domain/algorithms/deck-layer-style.d.ts +34 -0
- package/dist/src/domain/algorithms/maplibre-style.d.ts +63 -0
- package/dist/src/domain/algorithms/raster-color-ramps.d.ts +37 -0
- package/dist/src/domain/algorithms/scene-layer-type.d.ts +25 -0
- package/dist/src/domain/algorithms/symbol-compile.d.ts +100 -0
- package/dist/src/domain/algorithms/symbol-params.d.ts +90 -0
- package/dist/src/domain/map/bounds.d.ts +8 -0
- package/dist/src/domain/map/constants.d.ts +40 -0
- package/dist/src/domain/map/layer-builders.d.ts +32 -0
- package/dist/src/domain/map/rendered-layers.d.ts +30 -0
- package/dist/src/domain/map/style-ready.d.ts +24 -0
- package/dist/src/domain/map/tile-url.d.ts +20 -0
- package/dist/src/domain/map/types.d.ts +128 -0
- package/dist/src/domain/models/deck-layer-style.d.ts +211 -0
- package/dist/src/domain/models/scene-layer-type.d.ts +23 -0
- package/dist/src/domain/models/symbol.d.ts +424 -0
- package/dist/src/lib/api.d.ts +82 -0
- package/dist/src/lib/auth-session.d.ts +22 -0
- package/dist/src/lib/raster-color-layer/RasterColorLayer.d.ts +48 -0
- package/dist/src/lib/raster-color-layer/TileGrid.d.ts +31 -0
- package/dist/src/lib/raster-color-layer/colorRamp.d.ts +18 -0
- package/dist/src/lib/raster-color-layer/shaders/raster-color.frag.d.ts +2 -0
- package/dist/src/lib/raster-color-layer/shaders/raster-color.vert.d.ts +2 -0
- package/dist/src/lib/raster-color-layer/zoomInterpolate.d.ts +2 -0
- package/dist/src/sdk/commands.d.ts +113 -0
- package/dist/src/sdk/context/keys.d.ts +148 -0
- package/dist/src/sdk/context/publishers.d.ts +198 -0
- package/dist/src/sdk/context/store.d.ts +78 -0
- package/dist/src/sdk/context/when.d.ts +69 -0
- package/dist/src/sdk/contributions/dispatch.d.ts +78 -0
- package/dist/src/sdk/contributions/panel-id.d.ts +25 -0
- package/dist/src/sdk/contributions/registry.d.ts +199 -0
- package/dist/src/sdk/contributions/symbol-renderers.d.ts +107 -0
- package/dist/src/sdk/contributions/types.d.ts +288 -0
- package/dist/src/sdk/contributions/views-bridge.d.ts +92 -0
- package/dist/src/sdk/define-plugin.d.ts +17 -0
- package/dist/src/sdk/facets/storage.d.ts +152 -0
- package/dist/src/sdk/facets/types.d.ts +370 -0
- package/dist/src/sdk/host-api.d.ts +256 -0
- package/dist/src/sdk/map-api.d.ts +288 -0
- package/dist/src/sdk/panels.d.ts +130 -0
- package/dist/src/sdk/plugin.d.ts +145 -0
- package/dist/src/sdk/rail-tools.d.ts +58 -0
- package/dist/src/sdk/scopes.d.ts +158 -0
- package/dist/src/systems/renderer/DeckSceneRenderer.d.ts +26 -0
- package/dist/src/systems/renderer/FlowFieldLayer.d.ts +68 -0
- package/dist/src/systems/renderer/LayerRendererRegistry.d.ts +132 -0
- package/dist/src/systems/renderer/authenticated-deck-load.d.ts +4 -0
- package/dist/src/systems/renderer/deck/deck-layer-builders.d.ts +29 -0
- package/dist/src/systems/renderer/deck/deck-layer-helpers.d.ts +21 -0
- package/dist/src/systems/renderer/deck/mvt-point-aggregation-layer.d.ts +107 -0
- package/dist/src/systems/renderer/flow-field/flow-field-resources.d.ts +84 -0
- package/dist/src/systems/renderer/flow-field/flow-field-shaders.d.ts +4 -0
- package/dist/src/systems/renderer/symbol/SpriteRegistry.d.ts +34 -0
- package/dist/src/systems/renderer/symbol/entries.d.ts +67 -0
- package/dist/src/types/analysis.d.ts +205 -0
- package/dist/src/types/common.d.ts +17 -0
- package/dist/src/types/extensions.d.ts +560 -0
- package/dist/src/types/gis.d.ts +242 -0
- package/dist/src/types/market-social.d.ts +378 -0
- package/package.json +47 -0
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DTOs for `ngis-extension` — the Stage 11 extension registry / market, its
|
|
3
|
+
* per-user installs, scene-level composition, and the boot / scene-resolve
|
|
4
|
+
* payloads the plugin loader consumes.
|
|
5
|
+
*
|
|
6
|
+
* Field names are the **wire** names; nothing is renamed to taste. Java
|
|
7
|
+
* `Instant` serializes as an ISO-8601 `string`; Java `JsonNode` maps to
|
|
8
|
+
* `unknown` unless the shape is genuinely frozen.
|
|
9
|
+
*
|
|
10
|
+
* Contract: `docs/extension_loader_stage/README.md` § "W1 kickoff — locked
|
|
11
|
+
* contracts" (W1.1 / W1.2) and `frontend-api-guide.md` §16.
|
|
12
|
+
*
|
|
13
|
+
* **Stage 15 additions are additive only.** The market's *social* shapes live in
|
|
14
|
+
* `./market-social` (kickoff-authored, read-only to a wave); the two members
|
|
15
|
+
* imported below are referenced from the existing DTOs rather than re-declared,
|
|
16
|
+
* so there is exactly one source of truth per wire shape.
|
|
17
|
+
*/
|
|
18
|
+
import type { RatingAggregateDto, VersionScanResultDto } from "./market-social";
|
|
19
|
+
/**
|
|
20
|
+
* Only `"ui-plugin"` ever has a loadable bundle. `"tool"` and `"ai-skill"`
|
|
21
|
+
* entries carry `bundleUrl`/`integrity` values that are *meaningless rather
|
|
22
|
+
* than absent* — always filter on `kind` before attempting a load, a
|
|
23
|
+
* truthiness check on `bundleUrl` is not enough.
|
|
24
|
+
*/
|
|
25
|
+
export type ExtensionKind = "ui-plugin" | "tool" | "ai-skill";
|
|
26
|
+
export type ExtensionStatus = "ACTIVE" | "DEPRECATED" | "REMOVED";
|
|
27
|
+
/** `GROUP` exists on the backend; v1 renders it read-only (no group-grant UI). */
|
|
28
|
+
export type ExtensionVisibility = "PRIVATE" | "GROUP" | "PUBLIC";
|
|
29
|
+
/**
|
|
30
|
+
* Extension *version* lifecycle. Deliberately distinct from
|
|
31
|
+
* {@link SkillVersionStatus} — a skill version reaching `ACTIVE` and its
|
|
32
|
+
* `ai-skill` extension version reaching `PUBLISHED` are independent events.
|
|
33
|
+
*/
|
|
34
|
+
export type ExtensionVersionStatus = "DRAFT" | "IN_REVIEW" | "PUBLISHED" | "REJECTED" | "YANKED";
|
|
35
|
+
/** `PINNED` requires a strict `x.y.z` version; `ai-skill` entries must be pinned. */
|
|
36
|
+
export type VersionPolicy = "LATEST" | "PINNED";
|
|
37
|
+
export type PrincipalType = "USER" | "GROUP";
|
|
38
|
+
/** `GET /api/extensions?scope=` */
|
|
39
|
+
export type CatalogScope = "mine" | "shared" | "public";
|
|
40
|
+
/**
|
|
41
|
+
* Why a scene-composed extension could not be resolved for the current viewer.
|
|
42
|
+
* `null` when the entry is available.
|
|
43
|
+
*
|
|
44
|
+
* The tool side used to collapse three distinct failures into the single value
|
|
45
|
+
* `reference_revoked` (`ExtensionKindReferenceValidator.java:106-112`). W2's T1
|
|
46
|
+
* splits them into `tool_missing` / `tool_disabled` / `tool_forbidden`, and
|
|
47
|
+
* routes a geoanalysis outage to the existing `dependency_unavailable` via a
|
|
48
|
+
* new `dependencyAvailable` component on `ToolReferenceStatus`.
|
|
49
|
+
*
|
|
50
|
+
* **`reference_revoked` stays in the union** (W2.1): it stops being emitted but
|
|
51
|
+
* older clients and any cached payload may still carry it, so neither the type
|
|
52
|
+
* nor its `Market.reasons.reference_revoked` key is removed this wave.
|
|
53
|
+
*
|
|
54
|
+
* The naming asymmetry is deliberate — `tool_disabled` names the tool's actual
|
|
55
|
+
* `enabled` field where the skill side's `skill_not_active` names its `status`
|
|
56
|
+
* column. Do not harmonize one into the other.
|
|
57
|
+
*
|
|
58
|
+
* Because every UI looks these up through `Market.reasons.*`, the rename stayed
|
|
59
|
+
* a one-file change.
|
|
60
|
+
*/
|
|
61
|
+
export type SceneResolveReason = "extension_forbidden" | "no_published_version" | "extension_version_yanked" | "version_policy_required" | "skill_missing" | "skill_not_active" | "skill_forbidden" | "dependency_unavailable" | "tool_missing" | "tool_disabled" | "tool_forbidden"
|
|
62
|
+
/** Legacy tool-side value — no longer emitted as of T1, kept for one wave. */
|
|
63
|
+
| "reference_revoked";
|
|
64
|
+
export interface ExtensionSummaryDto {
|
|
65
|
+
extId: string;
|
|
66
|
+
kind: ExtensionKind;
|
|
67
|
+
ownerId: string;
|
|
68
|
+
displayName: string;
|
|
69
|
+
summary: string | null;
|
|
70
|
+
iconKey: string | null;
|
|
71
|
+
category: string | null;
|
|
72
|
+
/** Free-form `JsonNode` on the wire — do not assume `string[]`. */
|
|
73
|
+
tags: unknown;
|
|
74
|
+
visibility: ExtensionVisibility;
|
|
75
|
+
status: ExtensionStatus;
|
|
76
|
+
latestPublishedVersion: string | null;
|
|
77
|
+
/**
|
|
78
|
+
* The **latest PUBLISHED version's** declared scopes (Stage 13 XB1) — what
|
|
79
|
+
* the market card renders. Empty when nothing is published.
|
|
80
|
+
*
|
|
81
|
+
* Optional because a payload from a gateway predating XB1 omits it entirely,
|
|
82
|
+
* and "the server did not say" must stay distinguishable from "asks for
|
|
83
|
+
* nothing": the card renders no scope line at all in the first case.
|
|
84
|
+
*/
|
|
85
|
+
permissions?: string[];
|
|
86
|
+
/**
|
|
87
|
+
* ZB1's additive social members (F15.6/F15.11), shipped on the wire 2026-08-11.
|
|
88
|
+
*
|
|
89
|
+
* **Optional, and deliberately so.** The server always sends them now, but a
|
|
90
|
+
* summary reconstructed from a pre-Stage-15 cached payload — or from a gateway
|
|
91
|
+
* that has not been redeployed — omits them, and "the server did not say" must
|
|
92
|
+
* stay distinguishable from "zero installs, unrated, unverified". Render the
|
|
93
|
+
* absent case as no line at all, exactly as `permissions` already does.
|
|
94
|
+
*
|
|
95
|
+
* `rating` is `null` until the first rating and its `mean` is `null` whenever
|
|
96
|
+
* `count` is 0 — **never render a 0 mean; there is no such score.**
|
|
97
|
+
*/
|
|
98
|
+
installCount?: number;
|
|
99
|
+
rating?: RatingAggregateDto | null;
|
|
100
|
+
publisherVerified?: boolean;
|
|
101
|
+
}
|
|
102
|
+
export interface ExtensionVersionSummaryDto {
|
|
103
|
+
/** Strict `x.y.z`. Contrast with a skill version, which is an integer. */
|
|
104
|
+
version: string;
|
|
105
|
+
status: ExtensionVersionStatus;
|
|
106
|
+
minNgisVersion: string;
|
|
107
|
+
bundleSize: number | null;
|
|
108
|
+
bundleSha256: string | null;
|
|
109
|
+
publishedAt: string | null;
|
|
110
|
+
createdAt: string;
|
|
111
|
+
/**
|
|
112
|
+
* This version's declared scopes (Stage 13 XB1) — **per version**, which is
|
|
113
|
+
* what makes a scope escalation between two versions visible from the
|
|
114
|
+
* detail page without fetching each one. Optional for the same reason as
|
|
115
|
+
* {@link ExtensionSummaryDto.permissions}.
|
|
116
|
+
*/
|
|
117
|
+
permissions?: string[];
|
|
118
|
+
}
|
|
119
|
+
/** `GET /api/extensions/{extId}` — note the nesting, this is not a flat summary. */
|
|
120
|
+
export interface ExtensionDetailDto {
|
|
121
|
+
extension: ExtensionSummaryDto;
|
|
122
|
+
versions: ExtensionVersionSummaryDto[];
|
|
123
|
+
}
|
|
124
|
+
/** Populated only for `tool` / `ai-skill` kinds; every field is nullable. */
|
|
125
|
+
export interface ExtensionReferenceDto {
|
|
126
|
+
provider: string | null;
|
|
127
|
+
toolId: string | null;
|
|
128
|
+
toolVersion: number | null;
|
|
129
|
+
skillId: string | null;
|
|
130
|
+
/** Skill versions are integers. */
|
|
131
|
+
skillVersion: number | null;
|
|
132
|
+
}
|
|
133
|
+
export interface ExtensionVersionDetailDto {
|
|
134
|
+
extId: string;
|
|
135
|
+
version: string;
|
|
136
|
+
status: ExtensionVersionStatus;
|
|
137
|
+
/** The package manifest as stored; shape-checked by the loader (F6), not here. */
|
|
138
|
+
manifest: PackageManifestDto | null;
|
|
139
|
+
minNgisVersion: string;
|
|
140
|
+
capabilitySummary: unknown;
|
|
141
|
+
/** Fixed to `"bundle.mjs"` in v1. */
|
|
142
|
+
entry: string | null;
|
|
143
|
+
bundleSize: number | null;
|
|
144
|
+
bundleSha256: string | null;
|
|
145
|
+
changelog: string | null;
|
|
146
|
+
submittedBy: string | null;
|
|
147
|
+
reviewedBy: string | null;
|
|
148
|
+
reviewNote: string | null;
|
|
149
|
+
publishedAt: string | null;
|
|
150
|
+
createdAt: string;
|
|
151
|
+
reference: ExtensionReferenceDto | null;
|
|
152
|
+
/** This version's declared scopes (Stage 13 XB1) — a projection of
|
|
153
|
+
* `manifest.permissions`, not separate storage. */
|
|
154
|
+
permissions?: string[];
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The `manifest.json` / boot-payload `manifest` shape.
|
|
158
|
+
*
|
|
159
|
+
* **F1 types it; F1 does not validate it** — validation belongs to F6 at load
|
|
160
|
+
* time, against the bundle actually being executed.
|
|
161
|
+
*/
|
|
162
|
+
export interface PackageManifestDto {
|
|
163
|
+
/** Matches `^[a-z0-9-]+(\.[a-z0-9-]+)+$`; `ngis.*` is reserved first-party. */
|
|
164
|
+
id: string;
|
|
165
|
+
kind: ExtensionKind;
|
|
166
|
+
name: string;
|
|
167
|
+
/** Strict `x.y.z`. */
|
|
168
|
+
version: string;
|
|
169
|
+
/** Strict `x.y.z`. */
|
|
170
|
+
minNgisVersion: string;
|
|
171
|
+
/** Fixed to `"bundle.mjs"` in v1. */
|
|
172
|
+
entry: string;
|
|
173
|
+
capabilities?: {
|
|
174
|
+
panels?: unknown;
|
|
175
|
+
railTools?: unknown;
|
|
176
|
+
layerTypes?: unknown;
|
|
177
|
+
/** E7 — `{id, paramsSchema}[]`, consumed by the codeenv plugin bridge. */
|
|
178
|
+
commands?: unknown;
|
|
179
|
+
};
|
|
180
|
+
description?: string;
|
|
181
|
+
icon?: string;
|
|
182
|
+
category?: string;
|
|
183
|
+
tags?: unknown;
|
|
184
|
+
homepage?: string;
|
|
185
|
+
publisher?: string;
|
|
186
|
+
changelog?: string;
|
|
187
|
+
}
|
|
188
|
+
export interface ExtensionInstallDto {
|
|
189
|
+
extId: string;
|
|
190
|
+
enabled: boolean;
|
|
191
|
+
versionPolicy: VersionPolicy;
|
|
192
|
+
pinnedVersion: string | null;
|
|
193
|
+
installedAt: string;
|
|
194
|
+
updatedAt: string | null;
|
|
195
|
+
/**
|
|
196
|
+
* Scopes the installer consented to (Stage 13 XB2, V4's `granted_scopes`).
|
|
197
|
+
* `null` for an install row that predates consent, which is **not** the same
|
|
198
|
+
* as `[]` — the former has never been asked, the latter refused everything.
|
|
199
|
+
*
|
|
200
|
+
* **Never trust this as the effective grant set (`V-85`).** The server
|
|
201
|
+
* intersects with the resolved version's `permissions` when it *writes*, and
|
|
202
|
+
* does not recompute when a later version **narrows** them, so a stale scope
|
|
203
|
+
* outlives the declaration that justified it. X5 intersects at read time; see
|
|
204
|
+
* `src/sdk/scopes.ts`.
|
|
205
|
+
*/
|
|
206
|
+
grantedScopes: string[] | null;
|
|
207
|
+
/** The user-leg storage blob (F13.7). Free-form; the schema is the plugin's. */
|
|
208
|
+
settings?: unknown;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* `GET|PUT /api/extensions/{extId}/settings` (Stage 13 XB2, W2 kickoff §8).
|
|
212
|
+
*
|
|
213
|
+
* The **user** storage leg of F13.7 — per (user, extension), backed by
|
|
214
|
+
* `ngis_extension_install.settings` (`JSONB`, V4). `settings` is free-form JSON
|
|
215
|
+
* and deliberately typed `unknown`: the settings *schema* lives in the
|
|
216
|
+
* extension's manifest, not in this DTO, and this client never normalizes it.
|
|
217
|
+
*
|
|
218
|
+
* **The envelope is asymmetric, and settled** (XB2, confirmed after the W2
|
|
219
|
+
* kickoff): the `PUT` takes the settings object **bare** as its body and
|
|
220
|
+
* answers `{"settings": <stored>}` — enveloped *out*, bare *in*. Both verbs
|
|
221
|
+
* `404` when the caller has no install row (and for an unknown `extId`), and
|
|
222
|
+
* `PUT null` clears the value and answers `{"settings": null}`.
|
|
223
|
+
*
|
|
224
|
+
* **Never byte-compare the echo against what was written.** The column is
|
|
225
|
+
* Postgres `jsonb`, which normalizes key order, whitespace, duplicate keys and
|
|
226
|
+
* number formatting, so a byte-identical round-trip is not achievable even when
|
|
227
|
+
* nothing is lost. A client that diffed stored-vs-written to decide whether to
|
|
228
|
+
* re-save would loop forever (XB2 row V-83).
|
|
229
|
+
*/
|
|
230
|
+
export interface ExtensionSettingsResponse {
|
|
231
|
+
settings: unknown | null;
|
|
232
|
+
}
|
|
233
|
+
export interface ExtensionShareDto {
|
|
234
|
+
principalType: PrincipalType;
|
|
235
|
+
principalId: string;
|
|
236
|
+
grantedBy: string;
|
|
237
|
+
grantedAt: string;
|
|
238
|
+
}
|
|
239
|
+
export interface ExtensionReviewQueueEntryDto {
|
|
240
|
+
extId: string;
|
|
241
|
+
displayName: string;
|
|
242
|
+
kind: ExtensionKind;
|
|
243
|
+
version: string;
|
|
244
|
+
status: ExtensionVersionStatus;
|
|
245
|
+
minNgisVersion: string;
|
|
246
|
+
bundleSize: number | null;
|
|
247
|
+
bundleSha256: string | null;
|
|
248
|
+
submittedBy: string | null;
|
|
249
|
+
createdAt: string;
|
|
250
|
+
/**
|
|
251
|
+
* ZB3's upload-scan result (F15.10), **advisory to the reviewer and never
|
|
252
|
+
* blocking**. `null` for every row uploaded before scanning existed and for
|
|
253
|
+
* every non-`ui-plugin` row — a `tool` or `ai-skill` version has no bundle to
|
|
254
|
+
* scan. `null` means *not scanned*; it does not mean *clean*, and the reviewer
|
|
255
|
+
* UI must say so rather than showing an empty findings list (Z6, W3).
|
|
256
|
+
*/
|
|
257
|
+
scan?: VersionScanResultDto | null;
|
|
258
|
+
}
|
|
259
|
+
/** One entry of `GET /api/extensions/me?ngisVersion=`. */
|
|
260
|
+
export interface BootExtensionEntryDto {
|
|
261
|
+
extId: string;
|
|
262
|
+
kind: ExtensionKind;
|
|
263
|
+
version: string;
|
|
264
|
+
enabled: boolean;
|
|
265
|
+
compatible: boolean;
|
|
266
|
+
yanked: boolean;
|
|
267
|
+
manifest: PackageManifestDto;
|
|
268
|
+
bundleUrl: string;
|
|
269
|
+
integrity: string;
|
|
270
|
+
/**
|
|
271
|
+
* The resolved version's declared scopes — a projection of
|
|
272
|
+
* `manifest.permissions` (Stage 13 XB1), where an absent key and `[]` mean
|
|
273
|
+
* the same thing.
|
|
274
|
+
*
|
|
275
|
+
* Optional here because the *field* can be absent from an older payload,
|
|
276
|
+
* which is not the same as "declares nothing": `readDeclaredPermissions`
|
|
277
|
+
* (`src/store/plugin-grants.ts`) falls back to the manifest, which every
|
|
278
|
+
* entry carries.
|
|
279
|
+
*/
|
|
280
|
+
permissions?: string[];
|
|
281
|
+
/**
|
|
282
|
+
* The resolved version's `contributes` block, projected out of the manifest by
|
|
283
|
+
* the server (`BootExtensionEntryDto.java:23`, `SceneExtensionEntryDto.java`).
|
|
284
|
+
*
|
|
285
|
+
* **Declared at the Stage 15 W3 kickoff, additively — the wire has carried it
|
|
286
|
+
* since Stage 13 and the TypeScript said nothing** (`V15-244`, the `V15-235`
|
|
287
|
+
* pattern again: a field on the Java DTO with no TypeScript twin).
|
|
288
|
+
*
|
|
289
|
+
* `unknown` rather than a parsed type on purpose: the only supported reader is
|
|
290
|
+
* `parseManifestContributes(manifest)` (`src/sdk/contributions/parse.ts:893`),
|
|
291
|
+
* which takes `unknown`, validates, and reports paths rooted at
|
|
292
|
+
* `manifest.contributes`. **Read the manifest, not this field** — it is a
|
|
293
|
+
* redundant projection, and a second parse path is how the two disagree.
|
|
294
|
+
*/
|
|
295
|
+
contributes?: unknown;
|
|
296
|
+
/**
|
|
297
|
+
* The caller's own consented scopes for this install (Stage 13 XB2).
|
|
298
|
+
*
|
|
299
|
+
* **Not a manifest projection** — install-row state, which is why it appears
|
|
300
|
+
* here and *deliberately not* on a scene-resolve entry: a viewer of a shared
|
|
301
|
+
* scene is not the installer and has no install row to read. That asymmetry
|
|
302
|
+
* is the one field-level difference between the two otherwise identical
|
|
303
|
+
* entry shapes, and `SceneExtensionEntryDto` omits it below so the types say
|
|
304
|
+
* so rather than leaving an always-`undefined` property to be misread.
|
|
305
|
+
*
|
|
306
|
+
* The server reports `[]` (never `null`) for an install nobody has consented
|
|
307
|
+
* for. `undefined` therefore means the field was absent from the payload —
|
|
308
|
+
* treated the same as "never asked", i.e. no effective grants until consent.
|
|
309
|
+
*
|
|
310
|
+
* **Never the effective grant set (`V-85`)** — see `resolveEffectiveGrants`.
|
|
311
|
+
*/
|
|
312
|
+
grantedScopes?: string[] | null;
|
|
313
|
+
}
|
|
314
|
+
export interface BootPayloadDto {
|
|
315
|
+
ngisVersionEcho: string;
|
|
316
|
+
extensions: BootExtensionEntryDto[];
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* One entry of `GET /api/extensions/scene/{sceneId}?ngisVersion=`.
|
|
320
|
+
*
|
|
321
|
+
* Structurally a boot entry plus `available`/`reason`, but an **unavailable**
|
|
322
|
+
* entry is far emptier than the kickoff's "boot DTO + two fields" wording
|
|
323
|
+
* suggests. `ExtensionSceneResolveService.java:100` constructs it as
|
|
324
|
+
* `new SceneExtensionEntryDto(extId, null, null, true, false, false, null,
|
|
325
|
+
* null, null, false, reason)` — so `kind` and `version` are `null` too, not
|
|
326
|
+
* just `manifest`/`bundleUrl`/`integrity`, and `enabled` is hard-coded `true`.
|
|
327
|
+
* Only `extId`, the three booleans and `reason` are meaningful when
|
|
328
|
+
* `available === false`.
|
|
329
|
+
*
|
|
330
|
+
* Practical consequence for every consumer: **narrow on `available` before
|
|
331
|
+
* reading `kind`**, because the `kind === "ui-plugin"` load filter cannot be
|
|
332
|
+
* applied to an unavailable entry at all.
|
|
333
|
+
*
|
|
334
|
+
* Disabled entries are omitted from the payload entirely; absence is not an
|
|
335
|
+
* error state and must not render a "missing" placeholder.
|
|
336
|
+
*/
|
|
337
|
+
export interface SceneExtensionEntryDto extends Omit<BootExtensionEntryDto, "kind" | "version" | "manifest" | "bundleUrl" | "integrity" | "grantedScopes"> {
|
|
338
|
+
kind: ExtensionKind | null;
|
|
339
|
+
version: string | null;
|
|
340
|
+
manifest: PackageManifestDto | null;
|
|
341
|
+
bundleUrl: string | null;
|
|
342
|
+
integrity: string | null;
|
|
343
|
+
/**
|
|
344
|
+
* The scene-leg storage blob for this entry (F13.7's viewer-read leg).
|
|
345
|
+
*
|
|
346
|
+
* **Frozen by the W3 kickoff ahead of its backend (`V-49`, option 1).** W2's
|
|
347
|
+
* X3 found that "a viewer of a shared scene reads the owner's settings" had
|
|
348
|
+
* no endpoint behind it: the composition `GET` is owner-only (`403`) and the
|
|
349
|
+
* gRPC `ScenePluginSummary` carried no settings, so the value never left
|
|
350
|
+
* `ngis-scene` and a viewer read `null`. **XB3 (W3) delivers the backend leg**
|
|
351
|
+
* — proto field, `ngis-scene` populate, `ngis-extension` map — and X9 wires
|
|
352
|
+
* the read. Until XB3 is deployed the field is simply absent, which is why it
|
|
353
|
+
* is optional rather than `unknown | null`.
|
|
354
|
+
*
|
|
355
|
+
* Owner-only on the **write** path regardless: writes ride the composition
|
|
356
|
+
* `PUT` and its `revision`, and that ACL is unchanged this stage.
|
|
357
|
+
*/
|
|
358
|
+
settings?: unknown;
|
|
359
|
+
available: boolean;
|
|
360
|
+
reason: SceneResolveReason | null;
|
|
361
|
+
}
|
|
362
|
+
export interface SceneResolvePayloadDto {
|
|
363
|
+
sceneId: string;
|
|
364
|
+
ngisVersionEcho: string;
|
|
365
|
+
extensions: SceneExtensionEntryDto[];
|
|
366
|
+
}
|
|
367
|
+
export interface SceneExtensionCompositionEntry {
|
|
368
|
+
/** Matches `^[a-z0-9-]+(\.[a-z0-9-]+)+$`, unique per scene. */
|
|
369
|
+
extId: string;
|
|
370
|
+
enabled: boolean;
|
|
371
|
+
versionPolicy: VersionPolicy;
|
|
372
|
+
/** Required and strict `x.y.z` when `versionPolicy === "PINNED"`. */
|
|
373
|
+
pinnedVersion?: string | null;
|
|
374
|
+
settings?: unknown;
|
|
375
|
+
}
|
|
376
|
+
export interface SceneExtensionComposition {
|
|
377
|
+
plugins: SceneExtensionCompositionEntry[];
|
|
378
|
+
/** Reserved/opaque. **Round-trip it verbatim** — never interpret it. */
|
|
379
|
+
layout?: unknown;
|
|
380
|
+
/**
|
|
381
|
+
* Opaque optimistic-concurrency token (Stage 12 V-17). Returned by GET/PUT; **echo it back on
|
|
382
|
+
* PUT** and a stale save is refused with `409` instead of silently erasing the other editor's
|
|
383
|
+
* entry — which is what happened before, verified live.
|
|
384
|
+
*
|
|
385
|
+
* Compare for equality only: it is a content digest, not an ordinal. Omitting it restores the
|
|
386
|
+
* old last-write-wins behaviour, so never drop it to "fix" a conflict.
|
|
387
|
+
*/
|
|
388
|
+
revision?: string | null;
|
|
389
|
+
}
|
|
390
|
+
export interface CreateExtensionRequest {
|
|
391
|
+
extId: string;
|
|
392
|
+
kind?: ExtensionKind;
|
|
393
|
+
displayName: string;
|
|
394
|
+
summary?: string;
|
|
395
|
+
description?: string;
|
|
396
|
+
homepage?: string;
|
|
397
|
+
category?: string;
|
|
398
|
+
tags?: unknown;
|
|
399
|
+
visibility?: ExtensionVisibility;
|
|
400
|
+
}
|
|
401
|
+
export interface UpdateExtensionRequest {
|
|
402
|
+
displayName?: string;
|
|
403
|
+
summary?: string;
|
|
404
|
+
description?: string;
|
|
405
|
+
homepage?: string;
|
|
406
|
+
category?: string;
|
|
407
|
+
tags?: unknown;
|
|
408
|
+
visibility?: ExtensionVisibility;
|
|
409
|
+
status?: ExtensionStatus;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* `POST /api/extensions/{extId}/versions/reference` — the JSON reference tuple
|
|
413
|
+
* that stands in for a multipart bundle on `tool` / `ai-skill` kinds. Supply
|
|
414
|
+
* either the tool triple or the skill pair, never both.
|
|
415
|
+
*/
|
|
416
|
+
export interface CreateReferenceVersionRequest {
|
|
417
|
+
version: string;
|
|
418
|
+
minNgisVersion: string;
|
|
419
|
+
/**
|
|
420
|
+
* Free text carried onto the DRAFT and rendered on the version row.
|
|
421
|
+
*
|
|
422
|
+
* **Added by Stage 14 Y6 (W4).** The backend DTO has always had it
|
|
423
|
+
* (`CreateReferenceVersionRequest.java:22`) and this type did not, so no
|
|
424
|
+
* caller could send one — a `tool`-kind listing published through the
|
|
425
|
+
* self-serve wizard had no way to say what changed between two versions of a
|
|
426
|
+
* recipe, and the omission was invisible because an absent optional field is
|
|
427
|
+
* not an error anywhere.
|
|
428
|
+
*/
|
|
429
|
+
changelog?: string;
|
|
430
|
+
provider?: string;
|
|
431
|
+
toolId?: string;
|
|
432
|
+
toolVersion?: number;
|
|
433
|
+
skillId?: string;
|
|
434
|
+
/** Integer — the exact ACTIVE skill version being referenced. */
|
|
435
|
+
skillVersion?: number;
|
|
436
|
+
}
|
|
437
|
+
export interface InstallExtensionRequest {
|
|
438
|
+
versionPolicy?: VersionPolicy;
|
|
439
|
+
pinnedVersion?: string;
|
|
440
|
+
/**
|
|
441
|
+
* The consent decision (Stage 13 XB2). The server **intersects it with the
|
|
442
|
+
* resolved version's declared `permissions`** and stores the intersection —
|
|
443
|
+
* extras are dropped silently rather than failing the install, so read
|
|
444
|
+
* `grantedScopes` back off the response instead of assuming an echo.
|
|
445
|
+
*
|
|
446
|
+
* An ungrantable scope (`layers:write`, `net:<origin>`), an unknown string
|
|
447
|
+
* or a duplicate is a `400`.
|
|
448
|
+
*/
|
|
449
|
+
grantedScopes?: string[];
|
|
450
|
+
}
|
|
451
|
+
export interface UpdateInstallRequest {
|
|
452
|
+
enabled?: boolean;
|
|
453
|
+
versionPolicy?: VersionPolicy;
|
|
454
|
+
pinnedVersion?: string;
|
|
455
|
+
/**
|
|
456
|
+
* Re-consent (Stage 13 XB2). **`null`/absent leaves the stored grants
|
|
457
|
+
* unchanged; `[]` revokes everything** — unlike the manifest's
|
|
458
|
+
* `permissions`, where empty ≡ absent. The asymmetry exists so a
|
|
459
|
+
* `PATCH {enabled:false}` cannot silently wipe consent while "revoke all"
|
|
460
|
+
* stays sayable.
|
|
461
|
+
*/
|
|
462
|
+
grantedScopes?: string[] | null;
|
|
463
|
+
}
|
|
464
|
+
export type ScopeAuditEventKind = "SCOPE_CONSENT" | "SCOPE_DENIAL";
|
|
465
|
+
/**
|
|
466
|
+
* `POST /api/extensions/{extId}/scope-events` → `202`, empty body.
|
|
467
|
+
*
|
|
468
|
+
* The actor is always the authenticated caller — there is no actor field, and
|
|
469
|
+
* a client cannot attribute an event to somebody else. `scopes` is required,
|
|
470
|
+
* non-empty, duplicate-free and must contain only grantable scopes: the body is
|
|
471
|
+
* client-reported, so an arbitrary string must not be mintable into the audit
|
|
472
|
+
* trail. An extension the caller cannot see answers `404`, not `403`.
|
|
473
|
+
*/
|
|
474
|
+
export interface ScopeAuditRequest {
|
|
475
|
+
event: ScopeAuditEventKind;
|
|
476
|
+
scopes: string[];
|
|
477
|
+
/** ≤120 chars, meaningful on a denial — the refused facet member. */
|
|
478
|
+
member?: string;
|
|
479
|
+
/** Strict `x.y.z` when present. */
|
|
480
|
+
version?: string;
|
|
481
|
+
}
|
|
482
|
+
export interface ShareExtensionRequest {
|
|
483
|
+
principalType: PrincipalType;
|
|
484
|
+
principalId: string;
|
|
485
|
+
}
|
|
486
|
+
/** Body of `publish` and `approve` — both optional-note. */
|
|
487
|
+
export interface PublishVersionRequest {
|
|
488
|
+
reviewNote?: string;
|
|
489
|
+
}
|
|
490
|
+
/** `reviewNote` is required and must be non-blank. */
|
|
491
|
+
export interface RejectVersionRequest {
|
|
492
|
+
reviewNote: string;
|
|
493
|
+
}
|
|
494
|
+
export interface YankVersionRequest {
|
|
495
|
+
reason: string;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* The preview's fixed host identity. **Never the previewed extension's own id**
|
|
499
|
+
* — a preview running under the real id would read and write that install row's
|
|
500
|
+
* grants and settings and pollute an identity the user may later actually adopt
|
|
501
|
+
* (F15.9). Mirrors `ExtensionPreviewService.PREVIEW_EXT_ID` on the wire; the
|
|
502
|
+
* fixture gate asserts the two agree rather than trusting this constant.
|
|
503
|
+
*/
|
|
504
|
+
export declare const PREVIEW_EXT_ID = "ngis.market-preview";
|
|
505
|
+
/**
|
|
506
|
+
* The F13.5 scopes a preview can **never** hold, whatever the version declares
|
|
507
|
+
* (F15.9): nothing a preview does may persist beyond its disposal, and a preview
|
|
508
|
+
* may not raise host chrome outside its own surface.
|
|
509
|
+
*
|
|
510
|
+
* Verified at the W3 kickoff against `NgisPermissionScope`'s frozen union
|
|
511
|
+
* (`src/sdk/contributions/types.ts:218-228`) rather than copied from prose —
|
|
512
|
+
* that check *was* backlog row `V15-061`, and both spellings reproduce exactly.
|
|
513
|
+
* The remaining eight scopes are grantable to a preview if the version declares
|
|
514
|
+
* them; the intersection is computed server-side and arrives as `grantedScopes`.
|
|
515
|
+
*/
|
|
516
|
+
export declare const PREVIEW_EXCLUDED_SCOPES: readonly ["storage:user", "ui:notify"];
|
|
517
|
+
/**
|
|
518
|
+
* `sceneId` / `expectedGeneration` are the Stage 19 lab fence, echoed from the
|
|
519
|
+
* caller's own lab read — a stale generation is refused `409`, and Z5 must
|
|
520
|
+
* surface that rather than retrying under a generation the user did not see.
|
|
521
|
+
* `version` absent means the latest PUBLISHED version (v1 previews PUBLISHED
|
|
522
|
+
* only; a reviewer-side `IN_REVIEW` preview is a recorded open tension, not a
|
|
523
|
+
* silent extension of F15.9).
|
|
524
|
+
*/
|
|
525
|
+
export interface ExtensionPreviewRequest {
|
|
526
|
+
sceneId: string;
|
|
527
|
+
expectedGeneration: number;
|
|
528
|
+
version?: string;
|
|
529
|
+
ngisVersion: string;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* A previewed version composed into the caller's `PLUGIN_UI_LAB` scene.
|
|
533
|
+
*
|
|
534
|
+
* **Nothing here is persisted** — no install row, no stored consent, no scene
|
|
535
|
+
* write. The `POST` is a read that has a consent meaning: `grantedScopes` is
|
|
536
|
+
* what launching consents to, and F15.9 requires Z5 to show that set *before*
|
|
537
|
+
* the launch, not after.
|
|
538
|
+
*
|
|
539
|
+
* `entry.extId` is {@link PREVIEW_EXT_ID}; `sourceExtId` is what is being
|
|
540
|
+
* previewed. Everything else on `entry` — version, manifest, contributes,
|
|
541
|
+
* bundle, integrity — is the previewed version verbatim.
|
|
542
|
+
*
|
|
543
|
+
* The three scope lists are disjoint by construction server-side:
|
|
544
|
+
* `declaredScopes` = `grantedScopes` ∪ `excludedScopes`. Render `excludedScopes`
|
|
545
|
+
* as *withheld*, never as absent — a preview silently missing a scope the
|
|
546
|
+
* version declares is exactly the confusion F15.9's visible refusal exists to
|
|
547
|
+
* prevent.
|
|
548
|
+
*/
|
|
549
|
+
export interface ExtensionPreviewDto {
|
|
550
|
+
previewId: string;
|
|
551
|
+
sourceExtId: string;
|
|
552
|
+
sceneId: string;
|
|
553
|
+
generation: number;
|
|
554
|
+
/** ISO-8601. The lab's TTL, not a second clock — the preview dies with the lab. */
|
|
555
|
+
expiresAt: string | null;
|
|
556
|
+
entry: SceneExtensionEntryDto;
|
|
557
|
+
declaredScopes: string[];
|
|
558
|
+
grantedScopes: string[];
|
|
559
|
+
excludedScopes: string[];
|
|
560
|
+
}
|