@hsuite/smart-engines-cli 1.7.0 → 1.8.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.
Files changed (52) hide show
  1. package/README.md +56 -7
  2. package/dist/__tests__/helpers/fixtures-image-hygiene.d.ts +18 -0
  3. package/dist/__tests__/helpers/fixtures-image-hygiene.d.ts.map +1 -0
  4. package/dist/__tests__/helpers/fixtures-image-hygiene.js +42 -0
  5. package/dist/__tests__/helpers/fixtures-image-hygiene.js.map +1 -0
  6. package/dist/_lib/baas.d.ts +12 -17
  7. package/dist/_lib/baas.d.ts.map +1 -1
  8. package/dist/_lib/baas.js +13 -1
  9. package/dist/_lib/baas.js.map +1 -1
  10. package/dist/_lib/framework.js +2 -2
  11. package/dist/_lib/image-hygiene.d.ts +36 -0
  12. package/dist/_lib/image-hygiene.d.ts.map +1 -0
  13. package/dist/_lib/image-hygiene.js +233 -0
  14. package/dist/_lib/image-hygiene.js.map +1 -0
  15. package/dist/_lib/run-fn.d.ts +34 -0
  16. package/dist/_lib/run-fn.d.ts.map +1 -0
  17. package/dist/_lib/run-fn.js +15 -0
  18. package/dist/_lib/run-fn.js.map +1 -0
  19. package/dist/_lib/subscription-client.d.ts +20 -0
  20. package/dist/_lib/subscription-client.d.ts.map +1 -1
  21. package/dist/_lib/subscription-client.js +23 -1
  22. package/dist/_lib/subscription-client.js.map +1 -1
  23. package/dist/_lib/transport.d.ts +62 -0
  24. package/dist/_lib/transport.d.ts.map +1 -0
  25. package/dist/_lib/transport.js +120 -0
  26. package/dist/_lib/transport.js.map +1 -0
  27. package/dist/commands/customer-scope.d.ts +48 -0
  28. package/dist/commands/customer-scope.d.ts.map +1 -0
  29. package/dist/commands/customer-scope.js +89 -0
  30. package/dist/commands/customer-scope.js.map +1 -0
  31. package/dist/commands/deploy.d.ts.map +1 -1
  32. package/dist/commands/deploy.js +3 -2
  33. package/dist/commands/deploy.js.map +1 -1
  34. package/dist/commands/governance.d.ts.map +1 -1
  35. package/dist/commands/governance.js +13 -2
  36. package/dist/commands/governance.js.map +1 -1
  37. package/dist/commands/personhood.d.ts.map +1 -1
  38. package/dist/commands/personhood.js +9 -4
  39. package/dist/commands/personhood.js.map +1 -1
  40. package/dist/commands/redeploy.d.ts.map +1 -1
  41. package/dist/commands/redeploy.js +3 -2
  42. package/dist/commands/redeploy.js.map +1 -1
  43. package/dist/commands/transactions.d.ts.map +1 -1
  44. package/dist/commands/transactions.js +2 -1
  45. package/dist/commands/transactions.js.map +1 -1
  46. package/dist/commands/verify.d.ts +4 -1
  47. package/dist/commands/verify.d.ts.map +1 -1
  48. package/dist/commands/verify.js +37 -22
  49. package/dist/commands/verify.js.map +1 -1
  50. package/dist/index.js +7 -0
  51. package/dist/index.js.map +1 -1
  52. package/package.json +1 -1
package/README.md CHANGED
@@ -99,6 +99,42 @@ After this, your smart-app boots in cluster-mode automatically.
99
99
 
100
100
  ---
101
101
 
102
+ ## Plaintext transport: HTTPS by default, one explicit opt-in
103
+
104
+ The CLI mints and carries credentials (`hsuite init`, `hsuite subscribe`), so it
105
+ does not talk plaintext `http://` to a public host. Every command that takes a
106
+ `--server` / `--gateway` — or reaches the validator through
107
+ `_lib/subscription-client.ts` — routes through ONE resolver
108
+ (`src/_lib/transport.ts`); no call site derives the flag from the URL scheme.
109
+
110
+ | Target | Behaviour |
111
+ |---|---|
112
+ | `https://…` | Accepted |
113
+ | `http://localhost`, `http://127.0.0.1`, `http://[::1]` | Accepted — the local-dev flow needs no flag |
114
+ | `http://<cluster-service>.svc[.cluster.local]` | Deferred to the SDK transport policy (which admits it) |
115
+ | any other `http://…` | **Refused** before the client is built |
116
+
117
+ A refusal names the opt-in:
118
+
119
+ ```
120
+ ✗ refusing to send credentials over plaintext http:// to gateway.example.com: the
121
+ smart-engines transport policy admits plain http:// only toward an in-cluster
122
+ service name (*.svc, *.cluster.local). Use https://, or re-run with --insecure
123
+ (or HSUITE_ALLOW_INSECURE=1) to allow it — local development only.
124
+ ```
125
+
126
+ The opt-in is one mechanism, either spelling:
127
+
128
+ ```sh
129
+ hsuite --insecure deploy --manifest ./app.json # global flag, before or after the subcommand
130
+ HSUITE_ALLOW_INSECURE=1 hsuite deploy --manifest ./app.json
131
+ ```
132
+
133
+ It is global (`--insecure` is registered once on the root program, not per
134
+ command) and applies to every command in the same invocation. The flag sets
135
+ `HSUITE_ALLOW_INSECURE=1`; only the exact value `1` counts. Use it only against
136
+ a host you operate yourself.
137
+
102
138
  ## Deployment commands
103
139
 
104
140
  Eight commands take a smart-app from a manifest to a running, manageable
@@ -111,10 +147,11 @@ deployment on the cluster. They all share base flags:
111
147
  | `--app-id <id>` | `DEPLOYED_APP_ID` → `SUBSCRIPTION_APP_ID` | App to act on |
112
148
 
113
149
  Every command constructs exactly **one** `BaasClient`
114
- (`{ hostUrl, appId, pathPrefix: '/host', allowInsecure, timeout }`) and
115
- authenticates it with the env XRPL signerconnecting straight to the public
116
- round-robin gateway (no cluster-discovery factory, whose per-cluster hostnames
117
- aren't reachable from a dev machine).
150
+ (`{ hostUrl, appId, pathPrefix: '/host', allowInsecure, timeout }`, where
151
+ `allowInsecure` comes from the shared resolver above`undefined` unless the
152
+ target is loopback or opted in) and authenticates it with the env XRPL signer —
153
+ connecting straight to the public round-robin gateway (no cluster-discovery
154
+ factory, whose per-cluster hostnames aren't reachable from a dev machine).
118
155
 
119
156
  ### The manifest (one canonical shape)
120
157
 
@@ -166,8 +203,8 @@ same set the smart-app's env schema reads (`XRPL_*`, `SUBSCRIPTION_APP_ID`,
166
203
  deploy-time / CLI-only knobs (e.g. `SUBSCRIPTION_NFT_SERIAL`, `VALIDATOR_API_KEY`)
167
204
  are **not** forwarded. The list lives in
168
205
  `packages/hsuite-cli/src/_lib/runtime-env.ts` (`RUNTIME_ENV_KEYS`), mirroring the
169
- smart-app schema (`apps/showcase/smart-app/src/config/env-validation.ts` in the
170
- hsuite-ecosystem repo).
206
+ smart-app schema (`smart-app/src/config/env-validation.ts` in the
207
+ `HSuiteNetwork/showcase-smart-app` repo).
171
208
 
172
209
  **Precedence:** the forwarded `.env.local` values are the base;
173
210
  **`manifest.backend.env` is overlaid last and WINS** for any key it sets. Use
@@ -264,6 +301,17 @@ The `strategy` field on the manifest/deploy request is **advisory**: a
264
301
  `recreate` request is coerced to `RollingUpdate` for multi-replica apps (with a
265
302
  warning).
266
303
 
304
+ ### Image-hygiene gate (HSUITEPT-5)
305
+
306
+ Right after `docker build` — and before any tag / login / push, also with
307
+ `--skip-build` — `hsuite deploy` scans the built image's compiled output
308
+ (`dist/`, `build/`, `lib/` under the image `WorkingDir`) and **aborts** if it
309
+ ships `.map`, `.d.ts` or `.tsbuildinfo` files: a pentest pulled a customer image
310
+ whose `dist/` read like source. Not skippable. Build the backend with
311
+ `sourceMap` / `declaration` off and `removeComments` on (a production tsconfig),
312
+ or keep those files out of the image (`.dockerignore`). `node_modules/` is never
313
+ scanned.
314
+
267
315
  ### `hsuite deploy` — THE canonical deploy path
268
316
 
269
317
  `hsuite deploy --manifest <file>` is the **single, canonical path** to deploy a
@@ -404,7 +452,8 @@ hsuite subscribe --env .env.local --tier builder
404
452
  ## Companion packages
405
453
 
406
454
  - **[`@hsuite/smart-engines-sdk`](https://www.npmjs.com/package/@hsuite/smart-engines-sdk)** — the underlying SDK that `hsuite` wraps. Use it directly when you need finer-grained control over auth, BaaS calls, or chain operations.
407
- - **[hsuite-ecosystem/apps/showcase](https://github.com/HSuiteNetwork/hsuite-ecosystem/tree/main/apps/showcase)** — a reference NestJS backend + Ionic dApp that demonstrate the full integration. Fork it as a starting point.
455
+ - **[showcase-smart-app](https://github.com/HSuiteNetwork/showcase-smart-app)** — a reference NestJS backend + Ionic dApp that demonstrate the full integration.
456
+ - **[boilerplate-smart-app](https://github.com/HSuiteNetwork/boilerplate-smart-app)** — the fork-and-go starting point for a new smart-app.
408
457
 
409
458
  ---
410
459
 
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Canned answers for the image-hygiene gate legs every `buildAndPush` runs
3
+ * (HSUITEPT-5): `docker inspect` → WorkingDir, `docker create` → container id,
4
+ * `docker cp` → the current {@link hygieneTar}, `docker rm` → nothing.
5
+ *
6
+ * Fold into any fake `execFileSync` / `runFn` as its fallthrough
7
+ * (`return hygieneLeg(file, args)`), so the gate sees a CLEAN image by default
8
+ * and the suite under test keeps asserting only its own legs. Plant an
9
+ * offending file with `hygieneTar = tarWith('dist/main.js.map')`.
10
+ */
11
+ export declare const HYGIENE_CID: string;
12
+ /** Empty archive = clean image. Reassign per test; reset in `beforeEach` where it matters. */
13
+ export declare let hygieneTar: Buffer;
14
+ export declare function setHygieneTar(tar: Buffer): void;
15
+ export declare function hygieneLeg(file: string, args: string[]): unknown;
16
+ /** One-entry ustar archive (enough to plant an offending file). */
17
+ export declare function tarWith(name: string): Buffer;
18
+ //# sourceMappingURL=fixtures-image-hygiene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures-image-hygiene.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/fixtures-image-hygiene.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,QAAiB,CAAC;AAE1C,8FAA8F;AAC9F,eAAO,IAAI,UAAU,EAAE,MAA2B,CAAC;AAEnD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAMhE;AAED,mEAAmE;AACnE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5C"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hygieneTar = exports.HYGIENE_CID = void 0;
4
+ exports.setHygieneTar = setHygieneTar;
5
+ exports.hygieneLeg = hygieneLeg;
6
+ exports.tarWith = tarWith;
7
+ /**
8
+ * Canned answers for the image-hygiene gate legs every `buildAndPush` runs
9
+ * (HSUITEPT-5): `docker inspect` → WorkingDir, `docker create` → container id,
10
+ * `docker cp` → the current {@link hygieneTar}, `docker rm` → nothing.
11
+ *
12
+ * Fold into any fake `execFileSync` / `runFn` as its fallthrough
13
+ * (`return hygieneLeg(file, args)`), so the gate sees a CLEAN image by default
14
+ * and the suite under test keeps asserting only its own legs. Plant an
15
+ * offending file with `hygieneTar = tarWith('dist/main.js.map')`.
16
+ */
17
+ exports.HYGIENE_CID = 'c'.repeat(64);
18
+ /** Empty archive = clean image. Reassign per test; reset in `beforeEach` where it matters. */
19
+ exports.hygieneTar = Buffer.alloc(1024);
20
+ function setHygieneTar(tar) {
21
+ exports.hygieneTar = tar;
22
+ }
23
+ function hygieneLeg(file, args) {
24
+ if (file !== 'docker')
25
+ return undefined;
26
+ if (args[0] === 'inspect')
27
+ return '/app\n';
28
+ if (args[0] === 'create')
29
+ return `${exports.HYGIENE_CID}\n`;
30
+ if (args[0] === 'cp')
31
+ return exports.hygieneTar;
32
+ return undefined;
33
+ }
34
+ /** One-entry ustar archive (enough to plant an offending file). */
35
+ function tarWith(name) {
36
+ const header = Buffer.alloc(512);
37
+ header.write(name, 0, 100, 'utf8');
38
+ header.write('00000000000\0', 124, 12, 'ascii');
39
+ header.write('0', 156, 1, 'ascii');
40
+ return Buffer.concat([header, Buffer.alloc(1024)]);
41
+ }
42
+ //# sourceMappingURL=fixtures-image-hygiene.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures-image-hygiene.js","sourceRoot":"","sources":["../../../src/__tests__/helpers/fixtures-image-hygiene.ts"],"names":[],"mappings":";;;AAeA,sCAEC;AAED,gCAMC;AAGD,0BAMC;AAlCD;;;;;;;;;GASG;AACU,QAAA,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAE1C,8FAA8F;AACnF,QAAA,UAAU,GAAW,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAEnD,SAAgB,aAAa,CAAC,GAAW;IACvC,kBAAU,GAAG,GAAG,CAAC;AACnB,CAAC;AAED,SAAgB,UAAU,CAAC,IAAY,EAAE,IAAc;IACrD,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC3C,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ;QAAE,OAAO,GAAG,mBAAW,IAAI,CAAC;IACpD,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,kBAAU,CAAC;IACxC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,mEAAmE;AACnE,SAAgB,OAAO,CAAC,IAAY;IAClC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { BaasClient } from '@hsuite/smart-engines-sdk';
2
2
  import type { EnvMap } from './env';
3
+ import type { RunFn } from './run-fn';
3
4
  /** Default per-app deploy timeout — `init` runs the smart-app entity DKG ceremony. */
4
5
  export declare const DEFAULT_DEPLOY_TIMEOUT_MS = 240000;
5
6
  /**
@@ -18,23 +19,11 @@ export type RegistryCreds = {
18
19
  repository: string;
19
20
  };
20
21
  /**
21
- * `execFileSync`-shaped seam. Throwing on a non-zero exit is the contract
22
- * `execFileSync` provides.
23
- *
24
- * The return value MATTERS for stdout-capturing invocations (the `docker push`
25
- * and `docker inspect` legs in {@link buildAndPush}): `execFileSync` returns the
26
- * child's stdout, and with `encoding: 'utf8'` that is a `string`. We parse the
27
- * push summary / `RepoDigests` out of it to recover the pushed manifest digest.
28
- * Legs run with inherited stdio (build/tag/login) return nothing meaningful.
29
- * Unit tests supply a fake that returns canned push/inspect stdout.
22
+ * The shell-out seam. Declared in `./run-fn` so `image-hygiene.ts` can take it
23
+ * without importing this module back (dependency-cruiser `no-circular`), and
24
+ * re-exported here because every existing caller imports it from `baas`.
30
25
  */
31
- export type RunFn = (file: string, args: string[], options: {
32
- input?: string;
33
- stdio?: unknown;
34
- env?: NodeJS.ProcessEnv;
35
- cwd?: string;
36
- encoding?: BufferEncoding;
37
- }) => unknown;
26
+ export type { RunFn } from './run-fn';
38
27
  export type ConnectAndAuthOpts = {
39
28
  /** Public gateway/host URL. */
40
29
  gateway: string;
@@ -51,7 +40,7 @@ export type ConnectAndAuthOpts = {
51
40
  clientFactory?: (config: {
52
41
  hostUrl: string;
53
42
  appId: string;
54
- allowInsecure: boolean;
43
+ allowInsecure: boolean | undefined;
55
44
  pathPrefix: string;
56
45
  timeout: number;
57
46
  }) => BaasClient;
@@ -88,6 +77,8 @@ export type BuildAndPushOpts = {
88
77
  platform?: string;
89
78
  /** Test seam — defaults to `execFileSync`. */
90
79
  runFn?: RunFn;
80
+ /** Progress sink for the image-hygiene gate (defaults to silent). */
81
+ log?: (message: string) => void;
91
82
  /** Push retry attempts (round-robin robot-auth can need a couple). Default 6. */
92
83
  pushAttempts?: number;
93
84
  /**
@@ -125,6 +116,10 @@ export declare function imageTarget(registry: RegistryCreds, tag: string): strin
125
116
  * - optional `<build>` (shell command) in `context`
126
117
  * - `docker build --platform linux/amd64 --provenance=false --sbom=false
127
118
  * -t hsuite-local/<name>:<tag> -f <dockerfile> <context>`
119
+ * - image-hygiene gate ({@link assertImageHygiene}, HSUITEPT-5): the built
120
+ * image's compiled output must ship no source maps / declarations — runs
121
+ * even with `--skip-build` (the image is about to be deployed either way)
122
+ * and ABORTS before any tag / login / push
128
123
  * - `docker tag <local> <server>/<repo>:<tag>`
129
124
  * - `docker login <server> -u <username> --password-stdin` ← username a
130
125
  * DISCRETE argv element; password on stdin
@@ -1 +1 @@
1
- {"version":3,"file":"baas.d.ts","sourceRoot":"","sources":["../../src/_lib/baas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"baas.d.ts","sourceRoot":"","sources":["../../src/_lib/baas.ts"],"names":[],"mappings":"AA+CA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAGpC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAItC,sFAAsF;AACtF,eAAO,MAAM,yBAAyB,SAAU,CAAC;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AAEpD,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,YAAY,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE;QACvB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,OAAO,GAAG,SAAS,CAAC;QACnC,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;KACjB,KAAK,UAAU,CAAC;CAClB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAiBlF;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,aAAa,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,qEAAqE;IACrE,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAExE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAmI3D;AAwDD,MAAM,MAAM,eAAe,GAAG;IAC5B,sDAAsD;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAIzD"}
package/dist/_lib/baas.js CHANGED
@@ -55,6 +55,8 @@ const child_process_1 = require("child_process");
55
55
  const smart_engines_sdk_1 = require("@hsuite/smart-engines-sdk");
56
56
  const env_1 = require("./env");
57
57
  const docker_1 = require("./docker");
58
+ const image_hygiene_1 = require("./image-hygiene");
59
+ const transport_1 = require("./transport");
58
60
  /** Default per-app deploy timeout — `init` runs the smart-app entity DKG ceremony. */
59
61
  exports.DEFAULT_DEPLOY_TIMEOUT_MS = 240_000;
60
62
  /**
@@ -75,7 +77,7 @@ async function connectAndAuth(opts) {
75
77
  const config = {
76
78
  hostUrl: opts.gateway,
77
79
  appId: opts.appId ?? 'pending',
78
- allowInsecure: opts.gateway.startsWith('http://'),
80
+ allowInsecure: (0, transport_1.resolveAllowInsecure)(opts.gateway),
79
81
  pathPrefix: '/host',
80
82
  timeout: opts.timeout ?? exports.DEFAULT_DEPLOY_TIMEOUT_MS,
81
83
  };
@@ -104,6 +106,10 @@ function imageTarget(registry, tag) {
104
106
  * - optional `<build>` (shell command) in `context`
105
107
  * - `docker build --platform linux/amd64 --provenance=false --sbom=false
106
108
  * -t hsuite-local/<name>:<tag> -f <dockerfile> <context>`
109
+ * - image-hygiene gate ({@link assertImageHygiene}, HSUITEPT-5): the built
110
+ * image's compiled output must ship no source maps / declarations — runs
111
+ * even with `--skip-build` (the image is about to be deployed either way)
112
+ * and ABORTS before any tag / login / push
107
113
  * - `docker tag <local> <server>/<repo>:<tag>`
108
114
  * - `docker login <server> -u <username> --password-stdin` ← username a
109
115
  * DISCRETE argv element; password on stdin
@@ -187,6 +193,12 @@ function buildAndPush(opts) {
187
193
  env: dockerEnv,
188
194
  });
189
195
  }
196
+ // HSUITEPT-5: never push (or deploy an already-pushed) image whose compiled
197
+ // output reads like source. Throws `ImageHygieneError` with the offending
198
+ // entries; nothing below runs. Not skippable — this is the platform-owned
199
+ // choke point for customer image hygiene, and app-side build config is
200
+ // never relied on.
201
+ (0, image_hygiene_1.assertImageHygiene)({ image: localTag, run, env: dockerEnv, log: opts.log });
190
202
  // #1679: aim the whole docker sequence at ONE origin when the caller resolved
191
203
  // a pin. `opts.registry` itself is left alone — see `pushHost`'s docblock for
192
204
  // why collapsing it breaks the downstream fan-out.
@@ -1 +1 @@
1
- {"version":3,"file":"baas.js","sourceRoot":"","sources":["../../src/_lib/baas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"baas.js","sourceRoot":"","sources":["../../src/_lib/baas.ts"],"names":[],"mappings":"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"}
@@ -15,8 +15,8 @@ exports.resolveSdkVersion = resolveSdkVersion;
15
15
  *
16
16
  * Detection is dependency-driven (reads the project's `package.json`), matching
17
17
  * the real showcase apps:
18
- * - backend (`apps/showcase/smart-app`): `@hsuite/smart-engines-sdk` + `@nestjs/core`
19
- * - frontend (`apps/showcase/ionic-dapp`): `@hsuite/native-connect-*` + `@ionic/angular`
18
+ * - backend (`smart-app/` in showcase-smart-app): `@hsuite/smart-engines-sdk` + `@nestjs/core`
19
+ * - frontend (`ionic-dapp/` in showcase-smart-app): `@hsuite/native-connect-*` + `@ionic/angular`
20
20
  *
21
21
  * This module is PURE I/O-at-the-edge: it reads one file and classifies. No
22
22
  * network, no clock.
@@ -0,0 +1,36 @@
1
+ import type { RunFn } from './run-fn';
2
+ /** Compiled-output directories a smart-app image conventionally ships under its `WorkingDir`. */
3
+ export declare const IMAGE_HYGIENE_SCAN_DIRS: readonly ["dist", "build", "lib"];
4
+ /** Entry suffixes that must never ship in a customer image. */
5
+ export declare const IMAGE_HYGIENE_FORBIDDEN_SUFFIXES: readonly [".map", ".d.ts", ".tsbuildinfo"];
6
+ /** Thrown when the built image ships source maps / declarations. `violations` lists every entry. */
7
+ export declare class ImageHygieneError extends Error {
8
+ readonly image: string;
9
+ readonly violations: string[];
10
+ constructor(image: string, violations: string[]);
11
+ }
12
+ /**
13
+ * Entry names of a (ustar / PAX / GNU) tar archive. Contents are skipped by
14
+ * size; only names are returned. Tolerant: stops at the first zero block or a
15
+ * truncated header, so a non-archive buffer yields `[]`.
16
+ */
17
+ export declare function listTarEntries(tar: Buffer): string[];
18
+ /** Entries that must never ship in a customer image. */
19
+ export declare function findImageHygieneViolations(entries: readonly string[]): string[];
20
+ export type AssertImageHygieneOpts = {
21
+ /** Local image ref to scan (the freshly built `hsuite-local/<name>:<tag>`). */
22
+ image: string;
23
+ /** `execFileSync`-shaped seam (see {@link RunFn}). */
24
+ run: RunFn;
25
+ /** Env threaded to every docker leg (carries `DOCKER_HOST`). */
26
+ env: NodeJS.ProcessEnv;
27
+ /** Progress / warning sink. */
28
+ log?: (message: string) => void;
29
+ };
30
+ /**
31
+ * Scan the built image's compiled output and THROW {@link ImageHygieneError}
32
+ * if it ships source maps, declaration files or tsbuildinfo. See the module
33
+ * header for the mechanism and the fail-closed contract.
34
+ */
35
+ export declare function assertImageHygiene(opts: AssertImageHygieneOpts): void;
36
+ //# sourceMappingURL=image-hygiene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-hygiene.d.ts","sourceRoot":"","sources":["../../src/_lib/image-hygiene.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEtC,iGAAiG;AACjG,eAAO,MAAM,uBAAuB,mCAAoC,CAAC;AAEzE,+DAA+D;AAC/D,eAAO,MAAM,gCAAgC,4CAA6C,CAAC;AAqB3F,oGAAoG;AACpG,qBAAa,iBAAkB,SAAQ,KAAK;IAExC,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE;gBADpB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAAE;CAWhC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA0BpD;AAED,wDAAwD;AACxD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAE/E;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,GAAG,EAAE,KAAK,CAAC;IACX,gEAAgE;IAChE,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,+BAA+B;IAC/B,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,GAAG,IAAI,CAyCrE"}
@@ -0,0 +1,233 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImageHygieneError = exports.IMAGE_HYGIENE_FORBIDDEN_SUFFIXES = exports.IMAGE_HYGIENE_SCAN_DIRS = void 0;
4
+ exports.listTarEntries = listTarEntries;
5
+ exports.findImageHygieneViolations = findImageHygieneViolations;
6
+ exports.assertImageHygiene = assertImageHygiene;
7
+ /**
8
+ * `hsuite deploy` image-hygiene gate — HSUITEPT-5 (#3245).
9
+ *
10
+ * The pentest pulled a customer image whose compiled output shipped 98
11
+ * `.js.map`, 49 `.d.ts` and JSDoc-preserved `.js` files: the backend read like
12
+ * source, handing an attacker every guard condition and fallback path before
13
+ * touching the live app. The registry side (tenant Harbor projects served to
14
+ * anonymous pullers) is closed in the provisioner; this closes the image side
15
+ * at the one choke point the platform owns for a customer build — the CLI,
16
+ * right after `docker build` and BEFORE anything is tagged, logged in, or
17
+ * pushed. App-side tsconfig/Dockerfile hygiene is never relied on.
18
+ *
19
+ * Mechanism (no shell inside the image — a distroless runtime has none):
20
+ * docker inspect -f '{{.Config.WorkingDir}}' <image> → where the app lives
21
+ * docker create <image> → throwaway container
22
+ * docker cp <id>:<workdir>/<dir> - → tar of each compiled
23
+ * output dir (dist/…)
24
+ * docker rm -f <id> → always, even on throw
25
+ * The tar is parsed for ENTRY NAMES only; contents are never inspected. Only
26
+ * the conventional compiled-output dirs are scanned, so `node_modules/` (whose
27
+ * published packages legitimately ship `.d.ts` / `.map`) is never a false hit.
28
+ *
29
+ * Fail closed: any offending entry aborts the deploy with the full list and
30
+ * the fix. An absent output dir is "nothing to scan" (a warning when none of
31
+ * the conventional dirs exists at all — the gate could not see the app code).
32
+ * A `docker cp` that fails for any OTHER reason is also fatal — only docker's
33
+ * own not-found signature means "absent"; anything else is a scan that did not
34
+ * happen, and the gate must never report one it did not perform.
35
+ */
36
+ const path_1 = require("path");
37
+ /** Compiled-output directories a smart-app image conventionally ships under its `WorkingDir`. */
38
+ exports.IMAGE_HYGIENE_SCAN_DIRS = ['dist', 'build', 'lib'];
39
+ /** Entry suffixes that must never ship in a customer image. */
40
+ exports.IMAGE_HYGIENE_FORBIDDEN_SUFFIXES = ['.map', '.d.ts', '.tsbuildinfo'];
41
+ /** `docker cp` of a compiled dist/ is a few MB; the default 1 MiB `execFileSync` buffer is not enough. */
42
+ const TAR_MAX_BUFFER_BYTES = 256 * 1024 * 1024;
43
+ /**
44
+ * Docker's "this path is not in the image" signature — the ONE `docker cp`
45
+ * failure that legitimately means "nothing to scan". Matched against the
46
+ * child's stderr, which docker populates for this wording.
47
+ *
48
+ * Deliberately NOT also matching a bare `no such file or directory`: that is
49
+ * the daemon's OS-level errno text, which appears when the READ failed (a
50
+ * pruned or corrupt overlay2 graph) rather than when the path is absent. The
51
+ * two must not collapse — a real not-found read as fatal only aborts a deploy
52
+ * the operator can re-run, while a broken read taken as "absent" silently
53
+ * disables the gate.
54
+ */
55
+ const DOCKER_CP_MISSING_RE = /could not find the file/i;
56
+ const TAR_BLOCK = 512;
57
+ /** Thrown when the built image ships source maps / declarations. `violations` lists every entry. */
58
+ class ImageHygieneError extends Error {
59
+ image;
60
+ violations;
61
+ constructor(image, violations) {
62
+ super(`Image hygiene gate (HSUITEPT-5): ${image} ships ${violations.length} file(s) that expose ` +
63
+ `the app's source and must not be deployed:\n` +
64
+ violations.map((v) => ` - ${v}`).join('\n') +
65
+ `\nBuild the backend with sourceMap/declaration OFF and removeComments ON (a production ` +
66
+ `tsconfig), or exclude them from the image (.dockerignore), then re-run \`hsuite deploy\`.`);
67
+ this.image = image;
68
+ this.violations = violations;
69
+ this.name = 'ImageHygieneError';
70
+ }
71
+ }
72
+ exports.ImageHygieneError = ImageHygieneError;
73
+ /**
74
+ * Entry names of a (ustar / PAX / GNU) tar archive. Contents are skipped by
75
+ * size; only names are returned. Tolerant: stops at the first zero block or a
76
+ * truncated header, so a non-archive buffer yields `[]`.
77
+ */
78
+ function listTarEntries(tar) {
79
+ const names = [];
80
+ let pendingLongName = null;
81
+ for (let off = 0; off + TAR_BLOCK <= tar.length;) {
82
+ const header = tar.subarray(off, off + TAR_BLOCK);
83
+ if (header.every((b) => b === 0))
84
+ break;
85
+ const size = parseInt(cstr(header, 124, 12) || '0', 8) || 0;
86
+ const type = String.fromCharCode(header[156] || 0x30);
87
+ const data = tar.subarray(off + TAR_BLOCK, off + TAR_BLOCK + size);
88
+ off += TAR_BLOCK + Math.ceil(size / TAR_BLOCK) * TAR_BLOCK;
89
+ if (type === 'L') {
90
+ pendingLongName = cstr(data, 0, data.length); // GNU long name
91
+ continue;
92
+ }
93
+ if (type === 'x') {
94
+ pendingLongName = paxPath(data.toString('utf8')) ?? pendingLongName; // PAX extended header
95
+ continue;
96
+ }
97
+ if (type === 'g')
98
+ continue; // PAX global header
99
+ const prefix = cstr(header, 345, 155);
100
+ const name = cstr(header, 0, 100);
101
+ names.push(pendingLongName ?? (prefix ? `${prefix}/${name}` : name));
102
+ pendingLongName = null;
103
+ }
104
+ return names;
105
+ }
106
+ /** Entries that must never ship in a customer image. */
107
+ function findImageHygieneViolations(entries) {
108
+ return entries.filter((e) => exports.IMAGE_HYGIENE_FORBIDDEN_SUFFIXES.some((s) => e.endsWith(s)));
109
+ }
110
+ /**
111
+ * Scan the built image's compiled output and THROW {@link ImageHygieneError}
112
+ * if it ships source maps, declaration files or tsbuildinfo. See the module
113
+ * header for the mechanism and the fail-closed contract.
114
+ */
115
+ function assertImageHygiene(opts) {
116
+ const { image, run, env } = opts;
117
+ const log = opts.log ?? (() => undefined);
118
+ const utf8 = { stdio: ['ignore', 'pipe', 'inherit'], encoding: 'utf8', env };
119
+ const workdir = asText(run('docker', ['inspect', '-f', '{{.Config.WorkingDir}}', image], utf8)) || '/';
120
+ const cid = asText(run('docker', ['create', image], utf8));
121
+ if (!cid)
122
+ throw new Error(`image hygiene gate: \`docker create ${image}\` returned no container id`);
123
+ try {
124
+ const violations = [];
125
+ let scanned = 0;
126
+ for (const dir of exports.IMAGE_HYGIENE_SCAN_DIRS) {
127
+ const entries = copyOut(run, `${cid}:${path_1.posix.join(workdir, dir)}`, env);
128
+ if (entries === null)
129
+ continue;
130
+ scanned++;
131
+ const files = entries.filter((e) => !e.endsWith('/'));
132
+ const bad = findImageHygieneViolations(files);
133
+ violations.push(...bad);
134
+ log(` image hygiene: ${dir}/ — ${files.length} file(s), ${bad.length} offending`);
135
+ }
136
+ if (scanned === 0) {
137
+ log(` ⚠ image hygiene: no compiled output found under ${workdir} (${exports.IMAGE_HYGIENE_SCAN_DIRS.join('/')}) — ` +
138
+ `nothing to scan`);
139
+ }
140
+ if (violations.length > 0)
141
+ throw new ImageHygieneError(image, violations);
142
+ }
143
+ finally {
144
+ // Best-effort reaping. A throw from a `finally` REPLACES the in-flight
145
+ // exception, so an unchecked `docker rm` would mask an `ImageHygieneError`
146
+ // verdict with a docker error — but a leaked container is still worth a
147
+ // line rather than being silent.
148
+ try {
149
+ run('docker', ['rm', '-f', cid], { stdio: 'ignore', env });
150
+ }
151
+ catch (err) {
152
+ log(` ⚠ image hygiene: could not remove scan container ${cid}: ${errorText(err)}`);
153
+ }
154
+ }
155
+ }
156
+ /**
157
+ * `docker cp <src> -` → entry names, or `null` when the path genuinely does not
158
+ * exist in the image.
159
+ *
160
+ * FAIL CLOSED: only docker's own not-found signature maps to `null`. Every
161
+ * other failure — a `maxBuffer` overflow on an unexpectedly huge directory, a
162
+ * dead container, a dropped daemon — is rethrown, because the gate cannot
163
+ * distinguish a broken read from an absent directory and must not report a scan
164
+ * it did not perform. stderr is PIPED rather than discarded so that signature
165
+ * is actually visible; with stderr `ignore`d, `execFileSync`'s error carries no
166
+ * docker text and EVERY failure reads as "not found".
167
+ */
168
+ function copyOut(run, src, env) {
169
+ let out;
170
+ try {
171
+ out = run('docker', ['cp', src, '-'], {
172
+ stdio: ['ignore', 'pipe', 'pipe'],
173
+ env,
174
+ maxBuffer: TAR_MAX_BUFFER_BYTES,
175
+ });
176
+ }
177
+ catch (err) {
178
+ const text = errorText(err);
179
+ if (DOCKER_CP_MISSING_RE.test(text))
180
+ return null;
181
+ throw new Error(`image hygiene gate: \`docker cp ${src} -\` failed, so the built image could not be ` +
182
+ `scanned — refusing to deploy an unscanned image: ${text}`);
183
+ }
184
+ // A non-Buffer means the seam decoded the archive, and a utf8 round-trip
185
+ // corrupts tar bytes into a buffer that parses as empty — a contract
186
+ // violation that would have read as "clean scan". Fail closed on it.
187
+ if (!Buffer.isBuffer(out)) {
188
+ throw new Error(`image hygiene gate: \`docker cp ${src} -\` returned ${typeof out}, not a tar buffer — ` +
189
+ `the run seam must not set \`encoding\` on this leg`);
190
+ }
191
+ return listTarEntries(out);
192
+ }
193
+ /**
194
+ * Message plus captured stderr of a thrown child-process error, for signature
195
+ * matching.
196
+ *
197
+ * TOTAL by construction: this runs inside `catch` blocks — including the
198
+ * `finally` that reaps the scan container — and `String()` throws on a
199
+ * null-prototype object or a hostile `Symbol.toPrimitive`. A throw from here
200
+ * would REPLACE the in-flight `ImageHygieneError`, i.e. the gate's verdict
201
+ * would be masked by a logging failure. Unstringifiable input therefore
202
+ * degrades to a literal rather than propagating.
203
+ */
204
+ function errorText(err) {
205
+ try {
206
+ const stderr = err.stderr;
207
+ const tail = Buffer.isBuffer(stderr) ? stderr.toString('utf8') : String(stderr ?? '');
208
+ const head = err instanceof Error ? err.message : String(err);
209
+ return `${head}\n${tail}`.trim();
210
+ }
211
+ catch {
212
+ return '[unstringifiable error]';
213
+ }
214
+ }
215
+ function asText(out) {
216
+ return typeof out === 'string'
217
+ ? out.trim()
218
+ : Buffer.isBuffer(out)
219
+ ? out.toString('utf8').trim()
220
+ : '';
221
+ }
222
+ /** NUL-terminated ASCII field of a tar header / GNU long-name block. */
223
+ function cstr(buf, start, len) {
224
+ const slice = buf.subarray(start, start + len);
225
+ const nul = slice.indexOf(0);
226
+ return slice.subarray(0, nul === -1 ? slice.length : nul).toString('utf8');
227
+ }
228
+ /** The `path=` record of a PAX extended header (`"<len> path=<value>\n"` lines). */
229
+ function paxPath(pax) {
230
+ const m = /(?:^|\n)\d+ path=([^\n]*)\n/.exec(pax);
231
+ return m ? m[1] : null;
232
+ }
233
+ //# sourceMappingURL=image-hygiene.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-hygiene.js","sourceRoot":"","sources":["../../src/_lib/image-hygiene.ts"],"names":[],"mappings":"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"}