@hsuite/smart-engines-cli 1.2.0 → 1.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.
Files changed (109) hide show
  1. package/README.md +272 -58
  2. package/dist/_lib/attestation.d.ts +45 -0
  3. package/dist/_lib/attestation.d.ts.map +1 -0
  4. package/dist/_lib/attestation.js +76 -0
  5. package/dist/_lib/attestation.js.map +1 -0
  6. package/dist/_lib/baas.d.ts +147 -0
  7. package/dist/_lib/baas.d.ts.map +1 -0
  8. package/dist/_lib/baas.js +260 -0
  9. package/dist/_lib/baas.js.map +1 -0
  10. package/dist/_lib/cluster.d.ts +6 -6
  11. package/dist/_lib/cluster.js +6 -6
  12. package/dist/_lib/deploy-manifest.d.ts +69 -0
  13. package/dist/_lib/deploy-manifest.d.ts.map +1 -0
  14. package/dist/_lib/deploy-manifest.js +87 -0
  15. package/dist/_lib/deploy-manifest.js.map +1 -0
  16. package/dist/_lib/docker.d.ts +82 -0
  17. package/dist/_lib/docker.d.ts.map +1 -0
  18. package/dist/_lib/docker.js +164 -0
  19. package/dist/_lib/docker.js.map +1 -0
  20. package/dist/_lib/faucet-client.d.ts +64 -0
  21. package/dist/_lib/faucet-client.d.ts.map +1 -0
  22. package/dist/_lib/faucet-client.js +92 -0
  23. package/dist/_lib/faucet-client.js.map +1 -0
  24. package/dist/_lib/framework.d.ts +59 -0
  25. package/dist/_lib/framework.d.ts.map +1 -0
  26. package/dist/_lib/framework.js +149 -0
  27. package/dist/_lib/framework.js.map +1 -0
  28. package/dist/_lib/frontend-guard.d.ts +13 -0
  29. package/dist/_lib/frontend-guard.d.ts.map +1 -0
  30. package/dist/_lib/frontend-guard.js +41 -0
  31. package/dist/_lib/frontend-guard.js.map +1 -0
  32. package/dist/_lib/registry-fanout.d.ts +114 -0
  33. package/dist/_lib/registry-fanout.d.ts.map +1 -0
  34. package/dist/_lib/registry-fanout.js +435 -0
  35. package/dist/_lib/registry-fanout.js.map +1 -0
  36. package/dist/_lib/runtime-env.d.ts +126 -0
  37. package/dist/_lib/runtime-env.d.ts.map +1 -0
  38. package/dist/_lib/runtime-env.js +172 -0
  39. package/dist/_lib/runtime-env.js.map +1 -0
  40. package/dist/_lib/subscription-client.d.ts +129 -18
  41. package/dist/_lib/subscription-client.d.ts.map +1 -1
  42. package/dist/_lib/subscription-client.js +268 -40
  43. package/dist/_lib/subscription-client.js.map +1 -1
  44. package/dist/_lib/subscription-env.d.ts +35 -0
  45. package/dist/_lib/subscription-env.d.ts.map +1 -1
  46. package/dist/_lib/subscription-env.js +46 -2
  47. package/dist/_lib/subscription-env.js.map +1 -1
  48. package/dist/commands/app-lifecycle.d.ts +36 -0
  49. package/dist/commands/app-lifecycle.d.ts.map +1 -0
  50. package/dist/commands/app-lifecycle.js +145 -0
  51. package/dist/commands/app-lifecycle.js.map +1 -0
  52. package/dist/commands/ci.d.ts +45 -0
  53. package/dist/commands/ci.d.ts.map +1 -0
  54. package/dist/commands/ci.js +174 -0
  55. package/dist/commands/ci.js.map +1 -0
  56. package/dist/commands/deploy-manifest.d.ts +11 -0
  57. package/dist/commands/deploy-manifest.d.ts.map +1 -0
  58. package/dist/commands/deploy-manifest.js +17 -0
  59. package/dist/commands/deploy-manifest.js.map +1 -0
  60. package/dist/commands/deploy.d.ts +70 -11
  61. package/dist/commands/deploy.d.ts.map +1 -1
  62. package/dist/commands/deploy.js +263 -150
  63. package/dist/commands/deploy.js.map +1 -1
  64. package/dist/commands/downgrade.js +1 -1
  65. package/dist/commands/downgrade.js.map +1 -1
  66. package/dist/commands/faucet.d.ts +78 -0
  67. package/dist/commands/faucet.d.ts.map +1 -0
  68. package/dist/commands/faucet.js +184 -0
  69. package/dist/commands/faucet.js.map +1 -0
  70. package/dist/commands/governance.js +1 -1
  71. package/dist/commands/governance.js.map +1 -1
  72. package/dist/commands/hist-balance.d.ts +1 -1
  73. package/dist/commands/hist-balance.js +1 -1
  74. package/dist/commands/init.js +1 -1
  75. package/dist/commands/list.d.ts +22 -0
  76. package/dist/commands/list.d.ts.map +1 -0
  77. package/dist/commands/list.js +81 -0
  78. package/dist/commands/list.js.map +1 -0
  79. package/dist/commands/personhood.js +2 -2
  80. package/dist/commands/personhood.js.map +1 -1
  81. package/dist/commands/redeploy.d.ts +62 -0
  82. package/dist/commands/redeploy.d.ts.map +1 -0
  83. package/dist/commands/redeploy.js +310 -0
  84. package/dist/commands/redeploy.js.map +1 -0
  85. package/dist/commands/status.d.ts +51 -0
  86. package/dist/commands/status.d.ts.map +1 -0
  87. package/dist/commands/status.js +138 -0
  88. package/dist/commands/status.js.map +1 -0
  89. package/dist/commands/subscribe.d.ts +94 -17
  90. package/dist/commands/subscribe.d.ts.map +1 -1
  91. package/dist/commands/subscribe.js +450 -81
  92. package/dist/commands/subscribe.js.map +1 -1
  93. package/dist/commands/transactions.d.ts +60 -0
  94. package/dist/commands/transactions.d.ts.map +1 -0
  95. package/dist/commands/transactions.js +101 -0
  96. package/dist/commands/transactions.js.map +1 -0
  97. package/dist/commands/update.d.ts +40 -0
  98. package/dist/commands/update.d.ts.map +1 -0
  99. package/dist/commands/update.js +114 -0
  100. package/dist/commands/update.js.map +1 -0
  101. package/dist/commands/verify.d.ts +10 -19
  102. package/dist/commands/verify.d.ts.map +1 -1
  103. package/dist/commands/verify.js +14 -23
  104. package/dist/commands/verify.js.map +1 -1
  105. package/dist/index.d.ts +12 -3
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +32 -3
  108. package/dist/index.js.map +1 -1
  109. package/package.json +11 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontend-guard.d.ts","sourceRoot":"","sources":["../../src/_lib/frontend-guard.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBxE"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertNoDeploySentinels = assertNoDeploySentinels;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ /**
7
+ * Fail-closed guard shared by `deploy` and `redeploy`: refuse to ship a
8
+ * frontend build that still carries unfilled `REPLACE_BEFORE_DEPLOY:<key>`
9
+ * placeholders (per-deployment config that was never set).
10
+ *
11
+ * Such a build refuses to bootstrap in the browser (the SPA's `main.ts` asserts
12
+ * on the sentinel prefix), and the CLI would otherwise tar+upload it silently —
13
+ * which is exactly how a non-bootstrapping bundle reached production. Matches
14
+ * the sentinel VALUE form (`:` followed by a letter) so it does NOT
15
+ * false-positive on the guard's own comparison literal (`REPLACE_BEFORE_DEPLOY:"`).
16
+ */
17
+ async function assertNoDeploySentinels(dir) {
18
+ const SENTINEL = /REPLACE_BEFORE_DEPLOY:[A-Za-z]/;
19
+ const TEXT_EXT = /\.(js|mjs|cjs|html|css|json|txt|map|webmanifest)$/i;
20
+ const hits = [];
21
+ const walk = async (d) => {
22
+ for (const ent of await fs_1.promises.readdir(d, { withFileTypes: true })) {
23
+ const p = (0, path_1.join)(d, ent.name);
24
+ if (ent.isDirectory())
25
+ await walk(p);
26
+ else if (TEXT_EXT.test(ent.name)) {
27
+ const m = (await fs_1.promises.readFile(p, 'utf8')).match(SENTINEL);
28
+ if (m)
29
+ hits.push(`${(0, path_1.relative)(dir, p)} (${m[0]}…)`);
30
+ }
31
+ }
32
+ };
33
+ await walk(dir);
34
+ if (hits.length) {
35
+ throw new Error(`frontend still contains REPLACE_BEFORE_DEPLOY placeholders — fill your ` +
36
+ `per-deployment config (e.g. environment.prod.ts) and rebuild before deploying. ` +
37
+ `Offending: ${hits.slice(0, 5).join(', ')}` +
38
+ (hits.length > 5 ? `, +${hits.length - 5} more` : ''));
39
+ }
40
+ }
41
+ //# sourceMappingURL=frontend-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontend-guard.js","sourceRoot":"","sources":["../../src/_lib/frontend-guard.ts"],"names":[],"mappings":";;AAcA,0DAuBC;AArCD,2BAAoC;AACpC,+BAAsC;AAEtC;;;;;;;;;;GAUG;AACI,KAAK,UAAU,uBAAuB,CAAC,GAAW;IACvD,MAAM,QAAQ,GAAG,gCAAgC,CAAC;IAClD,MAAM,QAAQ,GAAG,oDAAoD,CAAC;IACtE,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,KAAK,EAAE,CAAS,EAAiB,EAAE;QAC9C,KAAK,MAAM,GAAG,IAAI,MAAM,aAAE,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAC/D,MAAM,CAAC,GAAG,IAAA,WAAI,EAAC,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,GAAG,CAAC,WAAW,EAAE;gBAAE,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;iBAChC,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,MAAM,CAAC,GAAG,CAAC,MAAM,aAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACzD,IAAI,CAAC;oBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAA,eAAQ,EAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,yEAAyE;YACvE,iFAAiF;YACjF,cAAc,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC3C,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CACxD,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,114 @@
1
+ import { Buffer } from 'buffer';
2
+ /** A request against one cluster's Harbor Registry-v2 API. `path` is always `/v2/...` (or `/token...`). */
3
+ export type RegistryRequest = {
4
+ ip: string;
5
+ method: 'GET' | 'HEAD' | 'POST' | 'PUT' | 'PATCH';
6
+ path: string;
7
+ headers?: Record<string, string>;
8
+ body?: Buffer;
9
+ };
10
+ /** A Registry-v2 response. Header keys are lower-cased by the default transport. */
11
+ export type RegistryResponse = {
12
+ status: number;
13
+ headers: Record<string, string>;
14
+ body: Buffer;
15
+ };
16
+ /**
17
+ * The injectable network seam. The default implementation
18
+ * ({@link defaultTransport}) dials `req.ip:443` with TLS `servername` =
19
+ * the federated host and an added `Host` header = the federated host, with
20
+ * verification ON. Tests inject a fake — no real network.
21
+ */
22
+ export type RegistryTransport = (req: RegistryRequest) => Promise<RegistryResponse>;
23
+ /** A fan-out target — just the cluster-ingress IP. (Kept as a type for call-site clarity.) */
24
+ export type FanOutTarget = {
25
+ ip: string;
26
+ };
27
+ /** Per-endpoint outcome of {@link ensureImageOnClusters}. */
28
+ export type FanOutReport = {
29
+ targets: Array<{
30
+ ip: string;
31
+ outcome: 'present' | 'copied' | 'failed';
32
+ error?: string;
33
+ }>;
34
+ };
35
+ export type EnsureImageOpts = {
36
+ host: string;
37
+ repository: string;
38
+ tag: string;
39
+ /** The `sha256:<64hex>` manifest digest the push produced — the SSoT for present/verify. */
40
+ digest: string;
41
+ username: string;
42
+ password: string;
43
+ /** Cluster-ingress IPs (e.g. from {@link resolveClusterEndpoints}). */
44
+ endpoints: string[];
45
+ /** Test seam — defaults to {@link defaultTransport} bound to `host`. */
46
+ transport?: RegistryTransport;
47
+ };
48
+ /** A parsed `WWW-Authenticate: Bearer ...` token challenge. `realm` is mandatory. */
49
+ export type AuthChallenge = {
50
+ realm: string;
51
+ service?: string;
52
+ scope?: string;
53
+ };
54
+ /**
55
+ * Parse a `Bearer realm="...",service="...",scope="..."` challenge. Pure.
56
+ *
57
+ * Returns `null` for a non-Bearer scheme or a Bearer challenge missing the
58
+ * mandatory `realm` (without a realm there is nowhere to fetch a token from).
59
+ */
60
+ export declare function parseAuthChallenge(wwwAuthenticate: string): AuthChallenge | null;
61
+ /**
62
+ * DNS-resolve the federated host's A-records into the de-duplicated, sorted list
63
+ * of cluster-ingress IPs to fan out across. Injectable `resolve4` for tests;
64
+ * defaults to `dns.promises.resolve4`.
65
+ */
66
+ export declare function resolveClusterEndpoints(host: string, resolve4?: (h: string) => Promise<string[]>): Promise<string[]>;
67
+ /**
68
+ * Real {@link RegistryTransport}: HTTPS to `req.ip:443` with TLS SNI + HTTP
69
+ * `Host` pinned to `host`, verification ON. All registry paths are `/v2/...`;
70
+ * absolute token-realm URLs are handled by {@link fetchAbsolute}.
71
+ */
72
+ export declare function defaultTransport(host: string): RegistryTransport;
73
+ /**
74
+ * Fan out an already-pushed image to every cluster Harbor and prove it landed
75
+ * on all of them. See the module header for the full algorithm. Throws if no
76
+ * endpoint serves the digest to copy from, or if re-verification finds any
77
+ * endpoint not serving the pushed digest (the error names the failed IPs).
78
+ */
79
+ export declare function ensureImageOnClusters(opts: EnsureImageOpts): Promise<FanOutReport>;
80
+ /** Registry coordinates a push produced (shape of `BaasInitResponse.registry`). */
81
+ export type FanOutRegistry = {
82
+ server: string;
83
+ username: string;
84
+ password: string;
85
+ repository: string;
86
+ };
87
+ export type FanOutPushedImageOpts = {
88
+ registry: FanOutRegistry;
89
+ tag: string;
90
+ /** The `sha256:<64hex>` digest the push produced. */
91
+ digest: string;
92
+ /** Test seam — DNS A-record resolver (defaults to `dns.promises.resolve4`). */
93
+ resolve4?: (h: string) => Promise<string[]>;
94
+ /** Test seam — the registry transport. */
95
+ transport?: RegistryTransport;
96
+ /** Optional progress log sink (defaults to no-op). */
97
+ log?: (msg: string) => void;
98
+ };
99
+ /**
100
+ * The deploy-time entrypoint: take an image just pushed to the federated host
101
+ * (landed on ONE cluster) and guarantee it is present on EVERY cluster Harbor.
102
+ *
103
+ * Resolves the registry host's A-records into the cluster-ingress set, then:
104
+ * - 0/1 endpoint (a non-federated or local/dev registry, or DNS that doesn't
105
+ * fan out) → nothing to distribute; returns `null`.
106
+ * - ≥2 endpoints → {@link ensureImageOnClusters}, which copies + re-verifies
107
+ * and THROWS if any cluster ends up not serving the pushed digest.
108
+ *
109
+ * A DNS resolution failure is treated as "single-target" (logged, returns
110
+ * `null`) rather than fatal: a real federated push has already proven the host
111
+ * resolves, so a failure here means a dev/local registry where fan-out is moot.
112
+ */
113
+ export declare function fanOutPushedImage(opts: FanOutPushedImageOpts): Promise<FanOutReport | null>;
114
+ //# sourceMappingURL=registry-fanout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-fanout.d.ts","sourceRoot":"","sources":["../../src/_lib/registry-fanout.ts"],"names":[],"mappings":"AA8CA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAkBhC,2GAA2G;AAC3G,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,oFAAoF;AACpF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAEpF,8FAA8F;AAC9F,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C,6DAA6D;AAC7D,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1F,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,4FAA4F;IAC5F,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,wEAAwE;IACxE,SAAS,CAAC,EAAE,iBAAiB,CAAC;CAC/B,CAAC;AAEF,qFAAqF;AACrF,MAAM,MAAM,aAAa,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAgBhF;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAA0B,GAClE,OAAO,CAAC,MAAM,EAAE,CAAC,CAGnB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CA6BhE;AAwHD;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CA8FxF;AA8ED,mFAAmF;AACnF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,cAAc,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5C,0CAA0C;IAC1C,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,sDAAsD;IACtD,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CA+B9B"}
@@ -0,0 +1,435 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseAuthChallenge = parseAuthChallenge;
37
+ exports.resolveClusterEndpoints = resolveClusterEndpoints;
38
+ exports.defaultTransport = defaultTransport;
39
+ exports.ensureImageOnClusters = ensureImageOnClusters;
40
+ exports.fanOutPushedImage = fanOutPushedImage;
41
+ /**
42
+ * Synchronous Registry-v2 fan-out: copy one already-pushed image to EVERY
43
+ * federated Harbor cluster, then prove it landed on all of them.
44
+ *
45
+ * ## Why this exists
46
+ *
47
+ * `harbor.testnet.hsuite.network` is public-DNS round-robin over the 3
48
+ * cluster-ingress IPs, and each IP fronts its OWN independent Harbor instance.
49
+ * A single `docker push` (via {@link import('./baas').buildAndPush}) therefore
50
+ * lands the image on exactly ONE cluster — whichever IP the OS resolver picked
51
+ * that second. The Harbor cross-cluster replication mesh is unreliable, so we do
52
+ * the fan-out ourselves, at the Registry-v2 API level, and BLOCK the deploy
53
+ * until every cluster serves the exact pushed digest.
54
+ *
55
+ * ## How the fan-out works
56
+ *
57
+ * We talk to each cluster by its IP while pinning TLS SNI + the HTTP `Host`
58
+ * header to the federated hostname ({@link defaultTransport}) — the cert and the
59
+ * Harbor vhost are keyed on that name, the IP is just the dial target. The
60
+ * push-robot credential is BLS-deterministic and identical on all 3 Harbors, so
61
+ * one credential authenticates against every IP.
62
+ *
63
+ * 1. HEAD the tag on each IP; an IP whose `Docker-Content-Digest` equals the
64
+ * pushed digest is already `present`.
65
+ * 2. At least one IP MUST be present (the federated push landed somewhere); pick
66
+ * it as the copy SOURCE.
67
+ * 3. To each non-present IP, copy: pull the source manifest (exact bytes +
68
+ * content-type), and for the config blob + every layer blob, HEAD it on the
69
+ * dest and — only if absent — monolithically PUT it (start an upload session,
70
+ * fetch the blob from source, PUT to the session `Location` with `?digest=`).
71
+ * Then PUT the manifest with the source's exact bytes + content-type.
72
+ * 4. RE-VERIFY by HEADing the tag on EVERY IP. If any IP's served digest still
73
+ * mismatches, throw an aggregated error naming the failed IPs — a deploy must
74
+ * never proceed with a partially-distributed image.
75
+ *
76
+ * Single-arch only: the CLI builds `linux/amd64 --provenance=false --sbom=false`,
77
+ * so the artifact is always a single image manifest, never a manifest list /
78
+ * image index. A manifest-list mediaType is treated as a hard error rather than
79
+ * silently fanning out a list whose per-arch children we never copied.
80
+ *
81
+ * The transport is the ONLY injectable seam ({@link RegistryTransport}); specs
82
+ * pass an in-memory Harbor simulation so no real network is touched. The robot
83
+ * password rides only inside the Basic-auth header of the token request and is
84
+ * never logged.
85
+ */
86
+ const https = __importStar(require("https"));
87
+ const buffer_1 = require("buffer");
88
+ const dns_1 = require("dns");
89
+ /** Media types that identify a multi-arch manifest list / image index (unsupported). */
90
+ const MANIFEST_LIST_TYPES = [
91
+ 'application/vnd.docker.distribution.manifest.list.v2+json',
92
+ 'application/vnd.oci.image.index.v1+json',
93
+ ];
94
+ /** Accept header offered on manifest HEAD/GET — single-arch image manifests, either flavour. */
95
+ const MANIFEST_ACCEPT = [
96
+ 'application/vnd.docker.distribution.manifest.v2+json',
97
+ 'application/vnd.oci.image.manifest.v1+json',
98
+ // Also accept the list types so the registry hands us the list (we then reject
99
+ // it with a clear error) rather than 406-ing into an opaque failure.
100
+ ...MANIFEST_LIST_TYPES,
101
+ ].join(', ');
102
+ /**
103
+ * Parse a `Bearer realm="...",service="...",scope="..."` challenge. Pure.
104
+ *
105
+ * Returns `null` for a non-Bearer scheme or a Bearer challenge missing the
106
+ * mandatory `realm` (without a realm there is nowhere to fetch a token from).
107
+ */
108
+ function parseAuthChallenge(wwwAuthenticate) {
109
+ const trimmed = wwwAuthenticate.trim();
110
+ if (!/^Bearer\s/i.test(trimmed))
111
+ return null;
112
+ const params = trimmed.replace(/^Bearer\s+/i, '');
113
+ const out = {};
114
+ // Match `key="value"` pairs; values are quoted in every real registry challenge.
115
+ const re = /([a-zA-Z0-9_]+)="([^"]*)"/g;
116
+ let m;
117
+ while ((m = re.exec(params)) !== null) {
118
+ out[m[1]] = m[2];
119
+ }
120
+ if (!out.realm)
121
+ return null;
122
+ const result = { realm: out.realm };
123
+ if (out.service !== undefined)
124
+ result.service = out.service;
125
+ if (out.scope !== undefined)
126
+ result.scope = out.scope;
127
+ return result;
128
+ }
129
+ /**
130
+ * DNS-resolve the federated host's A-records into the de-duplicated, sorted list
131
+ * of cluster-ingress IPs to fan out across. Injectable `resolve4` for tests;
132
+ * defaults to `dns.promises.resolve4`.
133
+ */
134
+ async function resolveClusterEndpoints(host, resolve4 = (h) => dns_1.promises.resolve4(h)) {
135
+ const ips = await resolve4(host);
136
+ return Array.from(new Set(ips)).sort();
137
+ }
138
+ /**
139
+ * Real {@link RegistryTransport}: HTTPS to `req.ip:443` with TLS SNI + HTTP
140
+ * `Host` pinned to `host`, verification ON. All registry paths are `/v2/...`;
141
+ * absolute token-realm URLs are handled by {@link fetchAbsolute}.
142
+ */
143
+ function defaultTransport(host) {
144
+ return (req) => new Promise((resolvePromise, reject) => {
145
+ const r = https.request({
146
+ host: req.ip,
147
+ servername: host, // TLS SNI → the federated cert
148
+ port: 443,
149
+ method: req.method,
150
+ path: req.path,
151
+ rejectUnauthorized: true,
152
+ headers: { ...(req.headers ?? {}), Host: host },
153
+ }, (res) => {
154
+ const chunks = [];
155
+ res.on('data', (d) => chunks.push(d));
156
+ res.on('end', () => resolvePromise({
157
+ status: res.statusCode ?? 0,
158
+ headers: lowerCaseHeaders(res.headers),
159
+ body: buffer_1.Buffer.concat(chunks),
160
+ }));
161
+ });
162
+ r.on('error', reject);
163
+ if (req.body)
164
+ r.write(req.body);
165
+ r.end();
166
+ });
167
+ }
168
+ /** Lower-case header keys; collapse array values to the first entry. */
169
+ function lowerCaseHeaders(h) {
170
+ const out = {};
171
+ for (const [k, v] of Object.entries(h)) {
172
+ if (v === undefined)
173
+ continue;
174
+ out[k.toLowerCase()] = Array.isArray(v) ? v[0] : v;
175
+ }
176
+ return out;
177
+ }
178
+ /** Case-insensitive header read. */
179
+ function header(res, name) {
180
+ const lower = name.toLowerCase();
181
+ for (const [k, v] of Object.entries(res.headers)) {
182
+ if (k.toLowerCase() === lower)
183
+ return v;
184
+ }
185
+ return undefined;
186
+ }
187
+ /** Resolve a possibly-relative `Location` against the `/v2/...` request space. */
188
+ function locationPath(location) {
189
+ if (location.startsWith('http://') || location.startsWith('https://')) {
190
+ const u = new URL(location);
191
+ return u.pathname + u.search;
192
+ }
193
+ return location;
194
+ }
195
+ /**
196
+ * An authenticating Registry client over the injected transport. Transparently
197
+ * handles the 401 + Bearer-challenge dance: on a 401 it parses the challenge,
198
+ * fetches a token from the realm with HTTP Basic over the robot creds (caching
199
+ * it per `(ip, scope)`), then retries the original request with the Bearer.
200
+ */
201
+ function makeClient(transport, username, password) {
202
+ const tokens = new Map();
203
+ const basic = 'Basic ' + buffer_1.Buffer.from(`${username}:${password}`).toString('base64');
204
+ async function fetchToken(ip, realm, service, scope) {
205
+ const key = `${ip}|${scope ?? ''}`;
206
+ const cached = tokens.get(key);
207
+ if (cached)
208
+ return cached;
209
+ const u = new URL(realm);
210
+ if (service)
211
+ u.searchParams.set('service', service);
212
+ if (scope)
213
+ u.searchParams.set('scope', scope);
214
+ const res = await transport({
215
+ ip,
216
+ method: 'GET',
217
+ path: u.pathname + u.search,
218
+ headers: { Authorization: basic },
219
+ });
220
+ if (res.status !== 200) {
221
+ throw new Error(`token request to ${ip} (${realm}) failed: HTTP ${res.status}`);
222
+ }
223
+ const parsed = JSON.parse(res.body.toString('utf8'));
224
+ const token = parsed.token ?? parsed.access_token;
225
+ if (!token)
226
+ throw new Error(`token request to ${ip} returned no token`);
227
+ tokens.set(key, token);
228
+ return token;
229
+ }
230
+ /**
231
+ * Send `req`, transparently authenticating on a 401. `scopeHint` is the scope
232
+ * we proactively request (`repository:<repo>:pull,push`) when the challenge
233
+ * itself omits one.
234
+ */
235
+ async function send(req, scopeHint) {
236
+ const res = await transport(req);
237
+ if (res.status !== 401)
238
+ return res;
239
+ const wwwAuth = header(res, 'www-authenticate');
240
+ const challenge = wwwAuth ? parseAuthChallenge(wwwAuth) : null;
241
+ if (!challenge)
242
+ return res; // not a bearer challenge we can satisfy
243
+ const token = await fetchToken(req.ip, challenge.realm, challenge.service, challenge.scope ?? scopeHint);
244
+ return transport({
245
+ ...req,
246
+ headers: { ...(req.headers ?? {}), Authorization: `Bearer ${token}` },
247
+ });
248
+ }
249
+ return { send };
250
+ }
251
+ /**
252
+ * Parse a single-arch image manifest into its config + layer descriptors.
253
+ * Throws on a manifest-list / image-index mediaType (single-arch deploy only).
254
+ */
255
+ function parseManifest(bytes, contentType) {
256
+ const doc = JSON.parse(bytes.toString('utf8'));
257
+ const mediaType = contentType ?? doc.mediaType;
258
+ if (mediaType && MANIFEST_LIST_TYPES.includes(mediaType.split(';')[0].trim())) {
259
+ throw new Error(`manifest list not supported (single-arch deploy only): got mediaType "${mediaType}". ` +
260
+ 'The CLI builds linux/amd64 --provenance=false --sbom=false, which must yield a single image manifest.');
261
+ }
262
+ if (!doc.config?.digest || !Array.isArray(doc.layers)) {
263
+ throw new Error('source manifest is not a single-arch image manifest (no config/layers)');
264
+ }
265
+ return { config: doc.config, layers: doc.layers };
266
+ }
267
+ /**
268
+ * Fan out an already-pushed image to every cluster Harbor and prove it landed
269
+ * on all of them. See the module header for the full algorithm. Throws if no
270
+ * endpoint serves the digest to copy from, or if re-verification finds any
271
+ * endpoint not serving the pushed digest (the error names the failed IPs).
272
+ */
273
+ async function ensureImageOnClusters(opts) {
274
+ const transport = opts.transport ?? defaultTransport(opts.host);
275
+ const client = makeClient(transport, opts.username, opts.password);
276
+ const pullPushScope = `repository:${opts.repository}:pull,push`;
277
+ const manifestPath = `/v2/${opts.repository}/manifests/${opts.tag}`;
278
+ // 1. Which endpoints already serve the pushed digest?
279
+ const presence = await Promise.all(opts.endpoints.map(async (ip) => {
280
+ const res = await client.send({ ip, method: 'HEAD', path: manifestPath, headers: { Accept: MANIFEST_ACCEPT } }, pullPushScope);
281
+ const served = res.status === 200 ? header(res, 'docker-content-digest') : undefined;
282
+ return { ip, present: served === opts.digest };
283
+ }));
284
+ const source = presence.find((p) => p.present);
285
+ if (!source) {
286
+ throw new Error(`no cluster endpoint serves ${opts.repository}:${opts.tag}@${opts.digest} — ` +
287
+ 'nothing to copy from (the federated push must land on at least one cluster first).');
288
+ }
289
+ // Fast path: every endpoint already serves the digest (e.g. a single-cluster
290
+ // deployment, or a re-run). Nothing to copy — skip the source manifest GET.
291
+ if (presence.every((p) => p.present)) {
292
+ return { targets: presence.map((p) => ({ ip: p.ip, outcome: 'present' })) };
293
+ }
294
+ // 2. Pull the source manifest once (exact bytes + content-type).
295
+ const srcManifestRes = await client.send({ ip: source.ip, method: 'GET', path: manifestPath, headers: { Accept: MANIFEST_ACCEPT } }, pullPushScope);
296
+ if (srcManifestRes.status !== 200) {
297
+ throw new Error(`failed to read source manifest from ${source.ip}: HTTP ${srcManifestRes.status}`);
298
+ }
299
+ const manifestContentType = header(srcManifestRes, 'content-type');
300
+ const parsed = parseManifest(srcManifestRes.body, manifestContentType); // throws on manifest list
301
+ const blobDigests = [parsed.config.digest, ...parsed.layers.map((l) => l.digest)];
302
+ // 3. Copy to every non-present endpoint.
303
+ const report = { targets: [] };
304
+ for (const p of presence) {
305
+ if (p.present) {
306
+ report.targets.push({ ip: p.ip, outcome: 'present' });
307
+ continue;
308
+ }
309
+ await copyToDest({
310
+ client,
311
+ source: source.ip,
312
+ dest: p.ip,
313
+ repository: opts.repository,
314
+ tag: opts.tag,
315
+ pullPushScope,
316
+ blobDigests,
317
+ manifestBytes: srcManifestRes.body,
318
+ manifestContentType,
319
+ manifestPath,
320
+ });
321
+ report.targets.push({ ip: p.ip, outcome: 'copied' });
322
+ }
323
+ // 4. Re-verify the tag on EVERY endpoint; any mismatch is fatal.
324
+ const failures = [];
325
+ await Promise.all(opts.endpoints.map(async (ip) => {
326
+ const res = await client.send({ ip, method: 'HEAD', path: manifestPath, headers: { Accept: MANIFEST_ACCEPT } }, pullPushScope);
327
+ const served = res.status === 200 ? header(res, 'docker-content-digest') : undefined;
328
+ if (served !== opts.digest) {
329
+ failures.push(ip);
330
+ const t = report.targets.find((x) => x.ip === ip);
331
+ if (t) {
332
+ t.outcome = 'failed';
333
+ t.error = `re-verify: served digest ${served ?? '<none>'} !== ${opts.digest}`;
334
+ }
335
+ }
336
+ }));
337
+ if (failures.length > 0) {
338
+ throw new Error(`image fan-out incomplete: ${failures.sort().join(', ')} do not serve ` +
339
+ `${opts.repository}:${opts.tag}@${opts.digest} after copy — deploy aborted.`);
340
+ }
341
+ return report;
342
+ }
343
+ /** Copy the config + layer blobs (skipping ones the dest already has) and PUT the manifest. */
344
+ async function copyToDest(args) {
345
+ const { client, source, dest, repository, pullPushScope } = args;
346
+ for (const digest of args.blobDigests) {
347
+ // HEAD on dest — skip the upload entirely if the blob already exists.
348
+ const head = await client.send({ ip: dest, method: 'HEAD', path: `/v2/${repository}/blobs/${digest}` }, pullPushScope);
349
+ if (head.status === 200)
350
+ continue;
351
+ // Fetch the blob bytes from the source.
352
+ const blob = await client.send({ ip: source, method: 'GET', path: `/v2/${repository}/blobs/${digest}` }, pullPushScope);
353
+ if (blob.status !== 200) {
354
+ throw new Error(`failed to fetch blob ${digest} from source ${source}: HTTP ${blob.status}`);
355
+ }
356
+ // Start an upload session, then monolithic-PUT to its Location with ?digest=.
357
+ const start = await client.send({ ip: dest, method: 'POST', path: `/v2/${repository}/blobs/uploads/` }, pullPushScope);
358
+ if (start.status !== 202) {
359
+ throw new Error(`failed to start blob upload on ${dest}: HTTP ${start.status}`);
360
+ }
361
+ const location = header(start, 'location');
362
+ if (!location)
363
+ throw new Error(`blob upload on ${dest} returned no Location`);
364
+ const putPath = appendDigestQuery(locationPath(location), digest);
365
+ const put = await client.send({
366
+ ip: dest,
367
+ method: 'PUT',
368
+ path: putPath,
369
+ headers: { 'Content-Type': 'application/octet-stream' },
370
+ body: blob.body,
371
+ }, pullPushScope);
372
+ if (put.status !== 201) {
373
+ throw new Error(`failed to upload blob ${digest} to ${dest}: HTTP ${put.status}`);
374
+ }
375
+ }
376
+ // All blobs present on dest → PUT the manifest with the EXACT source bytes + content-type.
377
+ const headers = {};
378
+ if (args.manifestContentType)
379
+ headers['Content-Type'] = args.manifestContentType;
380
+ const put = await client.send({ ip: dest, method: 'PUT', path: args.manifestPath, headers, body: args.manifestBytes }, pullPushScope);
381
+ if (put.status !== 201 && put.status !== 200) {
382
+ throw new Error(`failed to PUT manifest to ${dest}: HTTP ${put.status}`);
383
+ }
384
+ }
385
+ /** Append `digest=<d>` to a `Location`, respecting any query string already present. */
386
+ function appendDigestQuery(path, digest) {
387
+ const sep = path.includes('?') ? '&' : '?';
388
+ return `${path}${sep}digest=${encodeURIComponent(digest)}`;
389
+ }
390
+ /**
391
+ * The deploy-time entrypoint: take an image just pushed to the federated host
392
+ * (landed on ONE cluster) and guarantee it is present on EVERY cluster Harbor.
393
+ *
394
+ * Resolves the registry host's A-records into the cluster-ingress set, then:
395
+ * - 0/1 endpoint (a non-federated or local/dev registry, or DNS that doesn't
396
+ * fan out) → nothing to distribute; returns `null`.
397
+ * - ≥2 endpoints → {@link ensureImageOnClusters}, which copies + re-verifies
398
+ * and THROWS if any cluster ends up not serving the pushed digest.
399
+ *
400
+ * A DNS resolution failure is treated as "single-target" (logged, returns
401
+ * `null`) rather than fatal: a real federated push has already proven the host
402
+ * resolves, so a failure here means a dev/local registry where fan-out is moot.
403
+ */
404
+ async function fanOutPushedImage(opts) {
405
+ const log = opts.log ?? (() => undefined);
406
+ const host = opts.registry.server.replace(/^https?:\/\//, '').replace(/:\d+$/, '');
407
+ let endpoints;
408
+ try {
409
+ endpoints = await resolveClusterEndpoints(host, opts.resolve4);
410
+ }
411
+ catch (err) {
412
+ log(` distribute: ${host} did not resolve (${err.message}); single-target, skipping fan-out`);
413
+ return null;
414
+ }
415
+ if (endpoints.length <= 1) {
416
+ log(` distribute: ${host} resolves to ${endpoints.length} endpoint(s); single-target, skipping fan-out`);
417
+ return null;
418
+ }
419
+ log(` distribute: fanning ${opts.registry.repository}:${opts.tag} to ${endpoints.length} clusters (${endpoints.join(', ')})`);
420
+ const report = await ensureImageOnClusters({
421
+ host,
422
+ repository: opts.registry.repository,
423
+ tag: opts.tag,
424
+ digest: opts.digest,
425
+ username: opts.registry.username,
426
+ password: opts.registry.password,
427
+ endpoints,
428
+ transport: opts.transport,
429
+ });
430
+ for (const t of report.targets) {
431
+ log(` distribute: ${t.ip} → ${t.outcome}${t.error ? ` (${t.error})` : ''}`);
432
+ }
433
+ return report;
434
+ }
435
+ //# sourceMappingURL=registry-fanout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-fanout.js","sourceRoot":"","sources":["../../src/_lib/registry-fanout.ts"],"names":[],"mappings":"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"}