@hsuite/smart-engines-sdk 3.0.2 → 3.0.3
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/CHANGELOG.md +28 -0
- package/README.md +43 -12
- package/dist/index.d.ts +109 -34
- package/dist/index.js +142 -20
- package/dist/index.js.map +1 -1
- package/dist/nestjs/index.d.ts +108 -34
- package/dist/nestjs/index.js +141 -20
- package/dist/nestjs/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.2.1 — 2026-05-16
|
|
4
|
+
|
|
5
|
+
**Documentation-only fix.** No runtime behavior change.
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- `DeploymentClient.init` JSDoc and `BaasInitResponse` type docs no longer
|
|
9
|
+
describe the registry as DOCR. The runtime arc routes pushes through a
|
|
10
|
+
per-tenant Harbor project (`hsuite-customers-<appId>`), and the credentials
|
|
11
|
+
returned in `registry.{server, username, password, repository}` are an
|
|
12
|
+
ephemeral project-scoped robot account whose secret is single-use and not
|
|
13
|
+
persisted server-side. README example aligned with the same wording.
|
|
14
|
+
|
|
15
|
+
## 3.2.0 — undocumented (PR-A → PR-I, 2026-05-12 → 2026-05-13)
|
|
16
|
+
|
|
17
|
+
Smart-app runtime arc surface — added `DeploymentClient` with the full
|
|
18
|
+
init → push → uploadFrontend → deploy flow plus lifecycle (suspend/
|
|
19
|
+
resume/update/rollback/delete) and ownership-gated metrics. See PRs
|
|
20
|
+
#516 (PR-A), #523 (PR-C), and #530 (PR-H) for details.
|
|
21
|
+
|
|
22
|
+
## 3.1.0 — undocumented (2026-05-12)
|
|
23
|
+
|
|
24
|
+
Added `CustomerSessionClient` for NFT-gated customer→smart-app auth (PR #496).
|
|
25
|
+
|
|
26
|
+
## 3.0.2 — undocumented (2026-05-12)
|
|
27
|
+
|
|
28
|
+
Dropped `nestjs` re-exports from the root entry to keep tree-shaking clean for
|
|
29
|
+
non-Nest consumers (PR #494).
|
|
30
|
+
|
|
3
31
|
## 3.0.0 — 2026-05-11
|
|
4
32
|
|
|
5
33
|
**First publishable release.**
|
package/README.md
CHANGED
|
@@ -52,14 +52,24 @@ await baas.authenticate({
|
|
|
52
52
|
},
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
-
// 4.
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
// 4. Initialise a free_testnet smart-app via the four-step deploy flow
|
|
56
|
+
// (init → docker push → optional uploadFrontend → deploy). `init` runs
|
|
57
|
+
// the per-entity DKG ceremony on the cluster and returns the DKG entityId
|
|
58
|
+
// as `appId`, plus ephemeral push credentials for the cluster's per-tenant
|
|
59
|
+
// Harbor project (single-use secret — not persisted server-side).
|
|
60
|
+
const init = await baas.deployment.init({
|
|
61
|
+
name: 'my-smart-app',
|
|
62
|
+
port: 3000,
|
|
58
63
|
services: ['database', 'storage', 'messaging', 'functions'],
|
|
59
64
|
});
|
|
60
65
|
|
|
61
|
-
console.log(`
|
|
62
|
-
|
|
66
|
+
console.log(`Allocated smart-app ${init.appId}`);
|
|
67
|
+
console.log(`Push to: ${init.registry.server}/${init.registry.repository}:<tag>`);
|
|
68
|
+
baas.setAppId(init.appId);
|
|
69
|
+
|
|
70
|
+
// (out-of-band) docker login + docker push <init.registry.server>/<init.registry.repository>:v1
|
|
71
|
+
// (optional) await baas.deployment.uploadFrontend(init.appId, await fs.readFile('./bundle.tar.gz'));
|
|
72
|
+
// (deploy) await baas.deployment.deploy(init.appId, { tag: 'v1', replicas: 1 });
|
|
63
73
|
```
|
|
64
74
|
|
|
65
75
|
**Why XRPL?** Per the Smart Engines V3 architecture, XRPL is canonical for
|
|
@@ -166,19 +176,40 @@ await baas.agents.resume(agent.agentId);
|
|
|
166
176
|
const events = await baas.agents.getEvents(agent.agentId);
|
|
167
177
|
```
|
|
168
178
|
|
|
169
|
-
### Deployment
|
|
179
|
+
### Deployment (runtime orchestration — spec §6.1)
|
|
180
|
+
|
|
181
|
+
The four-step deploy flow: **init → docker push → (optional) uploadFrontend → deploy**.
|
|
170
182
|
|
|
171
183
|
```ts
|
|
172
|
-
|
|
173
|
-
|
|
184
|
+
// 1. init — allocate appId via DKG + receive ephemeral Harbor push credentials
|
|
185
|
+
const init = await baas.deployment.init({
|
|
186
|
+
name: 'my-smart-app',
|
|
187
|
+
port: 3000,
|
|
174
188
|
services: ['database', 'storage', 'messaging'],
|
|
175
|
-
config: { /* app-specific */ },
|
|
176
189
|
});
|
|
177
190
|
|
|
191
|
+
// 2. docker push — out-of-band, using the ephemeral creds returned above
|
|
192
|
+
// docker login -u <init.registry.username> -p <init.registry.password> <init.registry.server>
|
|
193
|
+
// docker push <init.registry.server>/<init.registry.repository>:v1
|
|
194
|
+
|
|
195
|
+
// 3. uploadFrontend — optional SPA tarball (content-addressed, mounted read-only)
|
|
196
|
+
await baas.deployment.uploadFrontend(init.appId, await fs.readFile('./bundle.tar.gz'));
|
|
197
|
+
|
|
198
|
+
// 4. deploy — reconcile to k8s
|
|
199
|
+
const deployed = await baas.deployment.deploy(init.appId, {
|
|
200
|
+
tag: 'v1',
|
|
201
|
+
replicas: 1,
|
|
202
|
+
env: { NODE_ENV: 'production' },
|
|
203
|
+
});
|
|
204
|
+
console.log(`live at ${deployed.url}`);
|
|
205
|
+
|
|
206
|
+
// Lifecycle + listing
|
|
178
207
|
const apps = await baas.deployment.list();
|
|
179
|
-
const info = await baas.deployment.get(appId);
|
|
180
|
-
await baas.deployment.
|
|
181
|
-
await baas.deployment.
|
|
208
|
+
const info = await baas.deployment.get(init.appId);
|
|
209
|
+
const status = await baas.deployment.status(init.appId);
|
|
210
|
+
await baas.deployment.suspend(init.appId);
|
|
211
|
+
await baas.deployment.resume(init.appId);
|
|
212
|
+
await baas.deployment.rollback(init.appId, { toTag: 'v0' });
|
|
182
213
|
```
|
|
183
214
|
|
|
184
215
|
---
|
package/dist/index.d.ts
CHANGED
|
@@ -1055,7 +1055,7 @@ export type HttpClient = {
|
|
|
1055
1055
|
get<T = any>(path: string): Promise<T>;
|
|
1056
1056
|
put<T = any>(path: string, body: unknown): Promise<T>;
|
|
1057
1057
|
delete<T = any>(path: string): Promise<T>;
|
|
1058
|
-
upload<T = any>(path: string, file: Blob | Buffer, filename: string, metadata?: Record<string, string
|
|
1058
|
+
upload<T = any>(path: string, file: Blob | Buffer, filename: string, metadata?: Record<string, string>, fieldName?: string): Promise<T>;
|
|
1059
1059
|
};
|
|
1060
1060
|
export type HttpClientConfig = {
|
|
1061
1061
|
baseUrl: string;
|
|
@@ -1197,7 +1197,6 @@ export type EntityCreationResponse = {
|
|
|
1197
1197
|
success: boolean;
|
|
1198
1198
|
entityId: string;
|
|
1199
1199
|
publicKeys: string[];
|
|
1200
|
-
signerIndices: number[];
|
|
1201
1200
|
threshold: number;
|
|
1202
1201
|
ceremonyIds: string[];
|
|
1203
1202
|
};
|
|
@@ -1217,7 +1216,6 @@ export type ReshareResponse = {
|
|
|
1217
1216
|
export type EntityDetails = {
|
|
1218
1217
|
success: boolean;
|
|
1219
1218
|
payload?: unknown;
|
|
1220
|
-
signerIndices?: number[];
|
|
1221
1219
|
validators?: string[];
|
|
1222
1220
|
publicKeys?: string[];
|
|
1223
1221
|
error?: string;
|
|
@@ -2098,7 +2096,7 @@ declare function xlmToStroops(xlm: string | number): string;
|
|
|
2098
2096
|
declare function validateBitcoinAddress(address: string): boolean;
|
|
2099
2097
|
declare function satoshisToBtc(satoshis: string | number): string;
|
|
2100
2098
|
declare function btcToSatoshis(btc: string | number): string;
|
|
2101
|
-
export type BaasService = "auth" | "database" | "storage" | "functions" | "messaging";
|
|
2099
|
+
export type BaasService = "auth" | "database" | "storage" | "functions" | "messaging" | "customer-session";
|
|
2102
2100
|
export type BaasSupportedChain = "hedera" | "xrpl" | "polkadot" | "solana";
|
|
2103
2101
|
export type BaasEndpoints = {
|
|
2104
2102
|
auth: string;
|
|
@@ -2193,24 +2191,6 @@ export type BaasSessionInfo = {
|
|
|
2193
2191
|
expiresAt?: number;
|
|
2194
2192
|
error?: string;
|
|
2195
2193
|
};
|
|
2196
|
-
export type BaasRegisterRequest = {
|
|
2197
|
-
name: string;
|
|
2198
|
-
services: BaasService[];
|
|
2199
|
-
environment?: Record<string, string>;
|
|
2200
|
-
limits?: {
|
|
2201
|
-
storage?: string;
|
|
2202
|
-
functions?: number;
|
|
2203
|
-
channels?: number;
|
|
2204
|
-
};
|
|
2205
|
-
};
|
|
2206
|
-
export type BaasRegisterResponse = {
|
|
2207
|
-
appId: string;
|
|
2208
|
-
name: string;
|
|
2209
|
-
status: DeployedAppStatus;
|
|
2210
|
-
services: string[];
|
|
2211
|
-
endpoints: BaasEndpoints;
|
|
2212
|
-
createdAt: string;
|
|
2213
|
-
};
|
|
2214
2194
|
export type BaasDocument = {
|
|
2215
2195
|
_id: string;
|
|
2216
2196
|
data: Record<string, unknown>;
|
|
@@ -2416,18 +2396,56 @@ export type BaasPublishResult = {
|
|
|
2416
2396
|
channel: string;
|
|
2417
2397
|
timestamp: string;
|
|
2418
2398
|
};
|
|
2419
|
-
export type
|
|
2399
|
+
export type BaasInitRequest = {
|
|
2420
2400
|
name: string;
|
|
2401
|
+
port: number;
|
|
2421
2402
|
services: BaasService[];
|
|
2422
|
-
|
|
2403
|
+
limits?: {
|
|
2404
|
+
cpu?: string;
|
|
2405
|
+
memory?: string;
|
|
2406
|
+
};
|
|
2423
2407
|
};
|
|
2424
|
-
export type
|
|
2408
|
+
export type BaasInitResponse = {
|
|
2425
2409
|
appId: string;
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2410
|
+
registry: {
|
|
2411
|
+
server: string;
|
|
2412
|
+
username: string;
|
|
2413
|
+
password: string;
|
|
2414
|
+
repository: string;
|
|
2415
|
+
};
|
|
2416
|
+
};
|
|
2417
|
+
export type BaasDeployRequest = {
|
|
2418
|
+
tag: string;
|
|
2419
|
+
replicas?: number;
|
|
2420
|
+
env?: Record<string, string>;
|
|
2421
|
+
resources?: {
|
|
2422
|
+
cpu?: string;
|
|
2423
|
+
memory?: string;
|
|
2424
|
+
};
|
|
2425
|
+
strategy?: "rolling" | "recreate";
|
|
2426
|
+
};
|
|
2427
|
+
export type BaasDeployResponse = {
|
|
2428
|
+
appId: string;
|
|
2429
|
+
status: string;
|
|
2430
|
+
url: string;
|
|
2431
|
+
};
|
|
2432
|
+
export type BaasUploadFrontendResponse = {
|
|
2433
|
+
bundleSha256: string;
|
|
2434
|
+
bundleSizeBytes: number;
|
|
2435
|
+
};
|
|
2436
|
+
export type BaasRollbackRequest = {
|
|
2437
|
+
toTag: string;
|
|
2438
|
+
};
|
|
2439
|
+
export type BaasRuntimeStatus = {
|
|
2440
|
+
appId: string;
|
|
2441
|
+
state: "PENDING_SUBSCRIPTION" | "ACTIVE" | "SUSPENDED" | "RETIRED";
|
|
2442
|
+
runtime?: {
|
|
2443
|
+
image: string;
|
|
2444
|
+
runtimeState: "NOT_DEPLOYED" | "DEPLOYING" | "RUNNING" | "FAILED" | "DEGRADED";
|
|
2445
|
+
replicas: number;
|
|
2446
|
+
lastReconciledAt?: string;
|
|
2447
|
+
lastError?: string;
|
|
2448
|
+
};
|
|
2431
2449
|
};
|
|
2432
2450
|
export type BaasAppListResponse = {
|
|
2433
2451
|
apps: DeployedAppInfo[];
|
|
@@ -2571,7 +2589,11 @@ export declare class MessagingClient {
|
|
|
2571
2589
|
export declare class DeploymentClient {
|
|
2572
2590
|
private readonly http;
|
|
2573
2591
|
constructor(http: HttpClient);
|
|
2574
|
-
|
|
2592
|
+
init(request: BaasInitRequest): Promise<BaasInitResponse>;
|
|
2593
|
+
uploadFrontend(appId: string, bundle: Blob | Buffer, filename?: string): Promise<BaasUploadFrontendResponse>;
|
|
2594
|
+
deploy(appId: string, request: BaasDeployRequest): Promise<BaasDeployResponse>;
|
|
2595
|
+
rollback(appId: string, request: BaasRollbackRequest): Promise<BaasDeployResponse>;
|
|
2596
|
+
status(appId: string): Promise<BaasRuntimeStatus>;
|
|
2575
2597
|
list(): Promise<BaasAppListResponse>;
|
|
2576
2598
|
get(appId: string): Promise<DeployedAppInfo>;
|
|
2577
2599
|
update(appId: string, updates: Partial<BaasDeployRequest>): Promise<DeployedAppInfo>;
|
|
@@ -2586,7 +2608,11 @@ export declare class DeploymentClient {
|
|
|
2586
2608
|
success: boolean;
|
|
2587
2609
|
status: string;
|
|
2588
2610
|
}>;
|
|
2589
|
-
getStats(): Promise<
|
|
2611
|
+
getStats(): Promise<{
|
|
2612
|
+
totalApps: number;
|
|
2613
|
+
activeApps: number;
|
|
2614
|
+
totalOwners: number;
|
|
2615
|
+
}>;
|
|
2590
2616
|
}
|
|
2591
2617
|
export type AgentStatus = "active" | "paused" | "revoked" | "pending";
|
|
2592
2618
|
export type AgentRegisterRequest = {
|
|
@@ -2711,6 +2737,55 @@ export declare class AgentsClient {
|
|
|
2711
2737
|
success: boolean;
|
|
2712
2738
|
}>;
|
|
2713
2739
|
}
|
|
2740
|
+
export type CustomerSessionChallenge = {
|
|
2741
|
+
challenge: string;
|
|
2742
|
+
};
|
|
2743
|
+
export type CustomerSessionVerifyRequest = {
|
|
2744
|
+
appId: string;
|
|
2745
|
+
chain: string;
|
|
2746
|
+
address: string;
|
|
2747
|
+
publicKey?: string;
|
|
2748
|
+
signature: string;
|
|
2749
|
+
challenge: string;
|
|
2750
|
+
};
|
|
2751
|
+
export type CustomerSessionToken = {
|
|
2752
|
+
token: string;
|
|
2753
|
+
sessionId: string;
|
|
2754
|
+
validatorId: string;
|
|
2755
|
+
expiresAt: string;
|
|
2756
|
+
sessionSecret: string;
|
|
2757
|
+
};
|
|
2758
|
+
export type CustomerSessionInfo = {
|
|
2759
|
+
sessionId: string;
|
|
2760
|
+
appId: string;
|
|
2761
|
+
customerChain: string;
|
|
2762
|
+
customerAddress: string;
|
|
2763
|
+
subscriptionContext?: {
|
|
2764
|
+
nftSerial: number;
|
|
2765
|
+
tier: "free_testnet" | "starter" | "professional" | "enterprise";
|
|
2766
|
+
expiresAt: string;
|
|
2767
|
+
allowedAutomations?: string[];
|
|
2768
|
+
};
|
|
2769
|
+
createdAt: string;
|
|
2770
|
+
expiresAt: string;
|
|
2771
|
+
lastActivityAt: string;
|
|
2772
|
+
};
|
|
2773
|
+
export declare class CustomerSessionClient {
|
|
2774
|
+
private readonly baseUrl;
|
|
2775
|
+
private readonly timeoutMs;
|
|
2776
|
+
constructor(baseUrl: string, timeoutMs?: number);
|
|
2777
|
+
challenge(input: {
|
|
2778
|
+
chain: string;
|
|
2779
|
+
address: string;
|
|
2780
|
+
}): Promise<CustomerSessionChallenge>;
|
|
2781
|
+
verify(req: CustomerSessionVerifyRequest): Promise<CustomerSessionToken>;
|
|
2782
|
+
validate(bearer: string): Promise<CustomerSessionInfo>;
|
|
2783
|
+
end(bearer: string): Promise<{
|
|
2784
|
+
revoked: boolean;
|
|
2785
|
+
sessionId: string;
|
|
2786
|
+
}>;
|
|
2787
|
+
private fetch;
|
|
2788
|
+
}
|
|
2714
2789
|
export type AuthenticateOptions = {
|
|
2715
2790
|
chain: BaasSupportedChain;
|
|
2716
2791
|
walletAddress: string;
|
|
@@ -2732,6 +2807,7 @@ export declare class BaasClient {
|
|
|
2732
2807
|
readonly messaging: MessagingClient;
|
|
2733
2808
|
readonly deployment: DeploymentClient;
|
|
2734
2809
|
readonly agents: AgentsClient;
|
|
2810
|
+
readonly customerSession: CustomerSessionClient;
|
|
2735
2811
|
constructor(config: BaasClientConfig);
|
|
2736
2812
|
setAppId(appId: string): void;
|
|
2737
2813
|
isAuthenticated(): boolean;
|
|
@@ -2744,7 +2820,6 @@ export declare class BaasClient {
|
|
|
2744
2820
|
authenticate(options: AuthenticateOptions): Promise<BaasAuthResult>;
|
|
2745
2821
|
validateSession(): Promise<BaasSessionInfo>;
|
|
2746
2822
|
logout(): Promise<void>;
|
|
2747
|
-
register(request: BaasRegisterRequest): Promise<BaasRegisterResponse>;
|
|
2748
2823
|
private requireAuth;
|
|
2749
2824
|
private getHeaders;
|
|
2750
2825
|
private post;
|
|
@@ -2776,7 +2851,7 @@ declare namespace stellar {
|
|
|
2776
2851
|
export { stroopsToXlm, validateStellarAddress, xlmToStroops };
|
|
2777
2852
|
}
|
|
2778
2853
|
declare namespace baas {
|
|
2779
|
-
export { AgentBalance, AgentEvent, AgentFundRequest, AgentInfo, AgentOperation, AgentRegisterRequest, AgentRules, AgentRulesValidationResult, AgentStatus, AgentTradeRequest, AgentWithdrawRequest, AgentsClient, AuthenticateOptions, BaasAppListResponse, BaasAuthConfig, BaasAuthResult, BaasChallengeRequest, BaasChallengeResponse, BaasChannelConfig, BaasClient, BaasClientConfig, BaasDeleteResult, BaasDeployRequest,
|
|
2854
|
+
export { AgentBalance, AgentEvent, AgentFundRequest, AgentInfo, AgentOperation, AgentRegisterRequest, AgentRules, AgentRulesValidationResult, AgentStatus, AgentTradeRequest, AgentWithdrawRequest, AgentsClient, AuthenticateOptions, BaasAppListResponse, BaasAuthConfig, BaasAuthResult, BaasChallengeRequest, BaasChallengeResponse, BaasChannelConfig, BaasClient, BaasClientConfig, BaasDeleteResult, BaasDeployRequest, BaasDeployResponse, BaasDocument, BaasEndpoints, BaasError, BaasErrorDetails, BaasErrorResponse, BaasFileInfo, BaasFileMetadata, BaasFindResult, BaasFunctionDeployRequest, BaasFunctionDeployResult, BaasFunctionInfo, BaasFunctionLog, BaasFunctionLogOptions, BaasFunctionResources, BaasFunctionResult, BaasFunctionRuntime, BaasHistoryOptions, BaasInitRequest, BaasInitResponse, BaasInsertResult, BaasMerkleProof, BaasMessage, BaasPresenceInfo, BaasPresenceMember, BaasPublishResult, BaasQueryOptions, BaasRollbackRequest, BaasRuntimeStatus, BaasService, BaasSessionInfo, BaasStateTransition, BaasStorageUsage, BaasSupportedChain, BaasTriggerType, BaasUpdateResult, BaasUploadFrontendResponse, BaasUploadResult, BaasVerifyRequest, ChannelSubscription, DatabaseClient, DatabaseStatsResponse, DbComparisonOperator, DbDocument, DbQuery, DeployedApp, DeployedAppInfo, DeployedAppLimits, DeployedAppStatus, DeployedAppUsage, DeploymentClient, DocumentProofResponse, FunctionsClient, MessageHandler, MessagingClient, StateRootResponse, StateTransitionsResponse, StorageClient, validateAgentRules };
|
|
2780
2855
|
}
|
|
2781
2856
|
declare namespace discovery {
|
|
2782
2857
|
export { MIRROR_NODE_URLS, MirrorNodeClient, MirrorNodeConfig, MirrorNodeError, TopicMessage, TopicMessagesResponse, ValidatorDiscoveryClient, ValidatorDiscoveryConfig, ValidatorInfo, ValidatorMetadata, ValidatorNetworkEndpoints };
|
package/dist/index.js
CHANGED
|
@@ -1725,14 +1725,14 @@ function createHttpClient(config) {
|
|
|
1725
1725
|
throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
|
|
1726
1726
|
}
|
|
1727
1727
|
}
|
|
1728
|
-
async function upload(path, file, filename, metadata) {
|
|
1728
|
+
async function upload(path, file, filename, metadata, fieldName = "file") {
|
|
1729
1729
|
const url = `${config.baseUrl}${path}`;
|
|
1730
1730
|
const controller = new AbortController();
|
|
1731
1731
|
const timeoutId = setTimeout(() => controller.abort(), timeout * 2);
|
|
1732
1732
|
try {
|
|
1733
1733
|
const formData = new FormData();
|
|
1734
1734
|
const blob = file instanceof Blob ? file : new Blob([new Uint8Array(file)]);
|
|
1735
|
-
formData.append(
|
|
1735
|
+
formData.append(fieldName, blob, filename);
|
|
1736
1736
|
if (metadata) {
|
|
1737
1737
|
for (const [key, value] of Object.entries(metadata)) {
|
|
1738
1738
|
formData.append(key, value);
|
|
@@ -1776,7 +1776,7 @@ function createHttpClient(config) {
|
|
|
1776
1776
|
get: (path) => request("GET", path),
|
|
1777
1777
|
put: (path, body) => request("PUT", path, body),
|
|
1778
1778
|
delete: (path) => request("DELETE", path),
|
|
1779
|
-
upload,
|
|
1779
|
+
upload: ((path, file, filename, metadata, fieldName) => upload(path, file, filename, metadata, fieldName)),
|
|
1780
1780
|
setAuthToken
|
|
1781
1781
|
};
|
|
1782
1782
|
return client;
|
|
@@ -3619,49 +3619,101 @@ var DeploymentClient = class {
|
|
|
3619
3619
|
}
|
|
3620
3620
|
http;
|
|
3621
3621
|
/**
|
|
3622
|
-
*
|
|
3622
|
+
* Step 1 — allocate appId + receive ephemeral push credentials for
|
|
3623
|
+
* the cluster's per-tenant Harbor project.
|
|
3624
|
+
*
|
|
3625
|
+
* Each app gets its own Harbor project (`hsuite-customers-<appId>`)
|
|
3626
|
+
* isolated by Harbor's RBAC. The push robot returned in
|
|
3627
|
+
* `registry.{username, password}` is scoped to that project only —
|
|
3628
|
+
* it cannot read or write any other tenant's images.
|
|
3629
|
+
*
|
|
3630
|
+
* **Single-use secret discipline:** `registry.password` is returned
|
|
3631
|
+
* exactly once and is NOT persisted server-side. Store it locally
|
|
3632
|
+
* for the `docker push` and discard. To rotate, call `init` again
|
|
3633
|
+
* (issues a new robot under the same project).
|
|
3634
|
+
*
|
|
3635
|
+
* Use the credentials to `docker login` + `docker push`, then call
|
|
3636
|
+
* {@link deploy} with the pushed image tag.
|
|
3637
|
+
*/
|
|
3638
|
+
async init(request) {
|
|
3639
|
+
return this.http.post("/api/deployment/apps/init", request);
|
|
3640
|
+
}
|
|
3641
|
+
/**
|
|
3642
|
+
* Step 3 (optional) — upload the SPA tarball.
|
|
3643
|
+
*
|
|
3644
|
+
* The tarball is content-addressed (SHA-256) and mounted read-only
|
|
3645
|
+
* into the customer's pod alongside the backend container. Returns
|
|
3646
|
+
* the hash + size so the caller can verify the upload.
|
|
3647
|
+
*/
|
|
3648
|
+
async uploadFrontend(appId, bundle, filename = "bundle.tar.gz") {
|
|
3649
|
+
return this.http.upload(
|
|
3650
|
+
`/api/deployment/apps/${encodeURIComponent(appId)}/frontend`,
|
|
3651
|
+
bundle,
|
|
3652
|
+
filename,
|
|
3653
|
+
void 0,
|
|
3654
|
+
"bundle"
|
|
3655
|
+
);
|
|
3656
|
+
}
|
|
3657
|
+
/**
|
|
3658
|
+
* Step 4 — reconcile the runtime to k8s.
|
|
3659
|
+
*
|
|
3660
|
+
* Returns immediately with `status: 'deploying'`. Poll {@link status}
|
|
3661
|
+
* until `runtime.runtimeState === 'RUNNING'` for the URL to be live.
|
|
3662
|
+
*/
|
|
3663
|
+
async deploy(appId, request) {
|
|
3664
|
+
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/deploy`, request);
|
|
3665
|
+
}
|
|
3666
|
+
/**
|
|
3667
|
+
* Roll back to a previously-deployed image tag (must exist in
|
|
3668
|
+
* `runtime.deploymentHistory[]`).
|
|
3623
3669
|
*/
|
|
3624
|
-
async
|
|
3625
|
-
return this.http.post(
|
|
3670
|
+
async rollback(appId, request) {
|
|
3671
|
+
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/rollback`, request);
|
|
3626
3672
|
}
|
|
3627
3673
|
/**
|
|
3628
|
-
*
|
|
3674
|
+
* Live combined lifecycle + runtime status of an app.
|
|
3675
|
+
*/
|
|
3676
|
+
async status(appId) {
|
|
3677
|
+
return this.http.get(`/api/deployment/apps/${encodeURIComponent(appId)}/status`);
|
|
3678
|
+
}
|
|
3679
|
+
/**
|
|
3680
|
+
* List all deployed apps for the authenticated developer.
|
|
3629
3681
|
*/
|
|
3630
3682
|
async list() {
|
|
3631
3683
|
return this.http.get("/api/deployment/apps");
|
|
3632
3684
|
}
|
|
3633
3685
|
/**
|
|
3634
|
-
* Get app details
|
|
3686
|
+
* Get app details.
|
|
3635
3687
|
*/
|
|
3636
3688
|
async get(appId) {
|
|
3637
3689
|
return this.http.get(`/api/deployment/apps/${encodeURIComponent(appId)}`);
|
|
3638
3690
|
}
|
|
3639
3691
|
/**
|
|
3640
|
-
* Update app configuration
|
|
3692
|
+
* Update app configuration. Runtime effect lands in PR-H.
|
|
3641
3693
|
*/
|
|
3642
3694
|
async update(appId, updates) {
|
|
3643
3695
|
return this.http.put(`/api/deployment/apps/${encodeURIComponent(appId)}`, updates);
|
|
3644
3696
|
}
|
|
3645
3697
|
/**
|
|
3646
|
-
* Delete an app
|
|
3698
|
+
* Delete an app. Runtime effect (namespace teardown) lands in PR-H.
|
|
3647
3699
|
*/
|
|
3648
3700
|
async delete(appId) {
|
|
3649
3701
|
return this.http.delete(`/api/deployment/apps/${encodeURIComponent(appId)}`);
|
|
3650
3702
|
}
|
|
3651
3703
|
/**
|
|
3652
|
-
* Suspend an app
|
|
3704
|
+
* Suspend an app. Runtime effect (scale to zero) lands in PR-H.
|
|
3653
3705
|
*/
|
|
3654
3706
|
async suspend(appId) {
|
|
3655
3707
|
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/suspend`, {});
|
|
3656
3708
|
}
|
|
3657
3709
|
/**
|
|
3658
|
-
* Resume a suspended app
|
|
3710
|
+
* Resume a suspended app. Runtime effect (scale back up) lands in PR-H.
|
|
3659
3711
|
*/
|
|
3660
3712
|
async resume(appId) {
|
|
3661
3713
|
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/resume`, {});
|
|
3662
3714
|
}
|
|
3663
3715
|
/**
|
|
3664
|
-
* Get deployment statistics
|
|
3716
|
+
* Get deployment statistics.
|
|
3665
3717
|
*/
|
|
3666
3718
|
async getStats() {
|
|
3667
3719
|
return this.http.get("/api/deployment/stats");
|
|
@@ -3791,6 +3843,78 @@ var AgentsClient = class {
|
|
|
3791
3843
|
}
|
|
3792
3844
|
};
|
|
3793
3845
|
|
|
3846
|
+
// src/baas/customer-session/index.ts
|
|
3847
|
+
var CustomerSessionClient = class {
|
|
3848
|
+
constructor(baseUrl, timeoutMs = 3e4) {
|
|
3849
|
+
this.baseUrl = baseUrl;
|
|
3850
|
+
this.timeoutMs = timeoutMs;
|
|
3851
|
+
}
|
|
3852
|
+
baseUrl;
|
|
3853
|
+
timeoutMs;
|
|
3854
|
+
/**
|
|
3855
|
+
* Step 1: ask the host to issue a fresh challenge for the customer to sign.
|
|
3856
|
+
*/
|
|
3857
|
+
async challenge(input) {
|
|
3858
|
+
return this.fetch("POST", "/api/customer-session/challenge", input);
|
|
3859
|
+
}
|
|
3860
|
+
/**
|
|
3861
|
+
* Step 2: submit the customer's signed challenge. On success returns a
|
|
3862
|
+
* short-lived bearer JWT scoped to {appId, chain, address}.
|
|
3863
|
+
*/
|
|
3864
|
+
async verify(req) {
|
|
3865
|
+
return this.fetch("POST", "/api/customer-session/verify", req);
|
|
3866
|
+
}
|
|
3867
|
+
/**
|
|
3868
|
+
* Validate a customer bearer + return the decoded session info. Used by
|
|
3869
|
+
* smart-app backends to authorise incoming customer requests.
|
|
3870
|
+
*/
|
|
3871
|
+
async validate(bearer) {
|
|
3872
|
+
return this.fetch("GET", "/api/customer-session/validate", void 0, bearer);
|
|
3873
|
+
}
|
|
3874
|
+
/**
|
|
3875
|
+
* Revoke a customer session. Idempotent.
|
|
3876
|
+
*/
|
|
3877
|
+
async end(bearer) {
|
|
3878
|
+
return this.fetch(
|
|
3879
|
+
"POST",
|
|
3880
|
+
"/api/customer-session/end",
|
|
3881
|
+
void 0,
|
|
3882
|
+
bearer
|
|
3883
|
+
);
|
|
3884
|
+
}
|
|
3885
|
+
async fetch(method, path, body, bearer) {
|
|
3886
|
+
const url = `${this.baseUrl}${path}`;
|
|
3887
|
+
const controller = new AbortController();
|
|
3888
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
3889
|
+
try {
|
|
3890
|
+
const headers = { "Content-Type": "application/json" };
|
|
3891
|
+
if (bearer) headers["Authorization"] = `Bearer ${bearer}`;
|
|
3892
|
+
const init = { method, headers, signal: controller.signal };
|
|
3893
|
+
if (body !== void 0) init.body = JSON.stringify(body);
|
|
3894
|
+
const response = await fetch(url, init);
|
|
3895
|
+
clearTimeout(timeoutId);
|
|
3896
|
+
if (!response.ok) {
|
|
3897
|
+
const errBody = await response.json().catch(() => ({}));
|
|
3898
|
+
const err = new Error(
|
|
3899
|
+
errBody.message ?? `customer-session ${path} failed: ${response.status} ${response.statusText}`
|
|
3900
|
+
);
|
|
3901
|
+
err.status = response.status;
|
|
3902
|
+
throw err;
|
|
3903
|
+
}
|
|
3904
|
+
const text = await response.text();
|
|
3905
|
+
if (!text) return void 0;
|
|
3906
|
+
return JSON.parse(text);
|
|
3907
|
+
} catch (error) {
|
|
3908
|
+
clearTimeout(timeoutId);
|
|
3909
|
+
const e = error;
|
|
3910
|
+
if (e.name === "AbortError") {
|
|
3911
|
+
throw new Error(`customer-session ${path} timeout`);
|
|
3912
|
+
}
|
|
3913
|
+
throw error;
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3916
|
+
};
|
|
3917
|
+
|
|
3794
3918
|
// src/baas/client.ts
|
|
3795
3919
|
var BaasClient = class {
|
|
3796
3920
|
hostUrl;
|
|
@@ -3815,6 +3939,8 @@ var BaasClient = class {
|
|
|
3815
3939
|
deployment;
|
|
3816
3940
|
/** Autonomous smart agent management */
|
|
3817
3941
|
agents;
|
|
3942
|
+
/** Customer→smart-app session bridge (TokenGate Face B). */
|
|
3943
|
+
customerSession;
|
|
3818
3944
|
constructor(config) {
|
|
3819
3945
|
this.allowInsecure = config.allowInsecure ?? false;
|
|
3820
3946
|
this.hostUrl = validateUrl2(config.hostUrl, this.allowInsecure);
|
|
@@ -3834,6 +3960,7 @@ var BaasClient = class {
|
|
|
3834
3960
|
this.messaging = new MessagingClient(this.http, getAppId);
|
|
3835
3961
|
this.deployment = new DeploymentClient(this.http);
|
|
3836
3962
|
this.agents = new AgentsClient(this.http);
|
|
3963
|
+
this.customerSession = new CustomerSessionClient(baseUrlWithPrefix, this.timeout);
|
|
3837
3964
|
}
|
|
3838
3965
|
/** Set the app ID (for newly registered apps) */
|
|
3839
3966
|
setAppId(appId) {
|
|
@@ -3860,7 +3987,7 @@ var BaasClient = class {
|
|
|
3860
3987
|
requireAppId() {
|
|
3861
3988
|
if (!this.appId) {
|
|
3862
3989
|
throw new BaasError(
|
|
3863
|
-
"App ID required.
|
|
3990
|
+
"App ID required. Provide appId in config (e.g. from a prior deployment.init() call).",
|
|
3864
3991
|
400
|
|
3865
3992
|
);
|
|
3866
3993
|
}
|
|
@@ -3907,12 +4034,6 @@ var BaasClient = class {
|
|
|
3907
4034
|
}
|
|
3908
4035
|
this.authToken = null;
|
|
3909
4036
|
}
|
|
3910
|
-
// ========== App Registration ==========
|
|
3911
|
-
/** Register a new app on the BaaS host */
|
|
3912
|
-
async register(request) {
|
|
3913
|
-
this.requireAuth();
|
|
3914
|
-
return this.post("/api/deployment/apps", request);
|
|
3915
|
-
}
|
|
3916
4037
|
// ========== HTTP Helpers ==========
|
|
3917
4038
|
requireAuth() {
|
|
3918
4039
|
if (!this.authToken) {
|
|
@@ -4007,6 +4128,7 @@ exports.CapabilityNotEnabledError = CapabilityNotEnabledError;
|
|
|
4007
4128
|
exports.CapabilityValidationError = CapabilityValidationError;
|
|
4008
4129
|
exports.CircuitBreaker = CircuitBreaker;
|
|
4009
4130
|
exports.CircuitBreakerOpenError = CircuitBreakerOpenError;
|
|
4131
|
+
exports.CustomerSessionClient = CustomerSessionClient;
|
|
4010
4132
|
exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = DEFAULT_CIRCUIT_BREAKER_CONFIG;
|
|
4011
4133
|
exports.DEFAULT_RETRY_CONFIG = DEFAULT_RETRY_CONFIG;
|
|
4012
4134
|
exports.DatabaseClient = DatabaseClient;
|