@wildo-ai/wildo-module-client 1.1.4 → 1.1.5

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 (44) hide show
  1. package/dist/esm/__tests__/lockfile-repair.service.test.d.ts +0 -0
  2. package/dist/esm/__tests__/lockfile-repair.service.test.d.ts.map +0 -0
  3. package/dist/esm/__tests__/lockfile-repair.service.test.js.map +0 -0
  4. package/dist/esm/__tests__/module-adopter.service.test.d.ts +0 -0
  5. package/dist/esm/__tests__/module-adopter.service.test.d.ts.map +0 -0
  6. package/dist/esm/__tests__/module-adopter.service.test.js.map +0 -0
  7. package/dist/esm/__tests__/module-packager.service.test.d.ts +0 -0
  8. package/dist/esm/__tests__/module-packager.service.test.d.ts.map +0 -0
  9. package/dist/esm/__tests__/module-packager.service.test.js.map +0 -0
  10. package/dist/esm/__tests__/provider-materialization-hook.test.d.ts +0 -0
  11. package/dist/esm/__tests__/provider-materialization-hook.test.d.ts.map +0 -0
  12. package/dist/esm/__tests__/provider-materialization-hook.test.js.map +0 -0
  13. package/dist/esm/__tests__/provider-sync-runner.test.d.ts +0 -0
  14. package/dist/esm/__tests__/provider-sync-runner.test.d.ts.map +0 -0
  15. package/dist/esm/__tests__/provider-sync-runner.test.js.map +0 -0
  16. package/dist/esm/__tests__/registry-lockfile.service.test.d.ts +0 -0
  17. package/dist/esm/__tests__/registry-lockfile.service.test.d.ts.map +0 -0
  18. package/dist/esm/__tests__/registry-lockfile.service.test.js.map +0 -0
  19. package/dist/esm/__tests__/registry-server-client.test.d.ts +0 -0
  20. package/dist/esm/__tests__/registry-server-client.test.d.ts.map +0 -0
  21. package/dist/esm/__tests__/registry-server-client.test.js.map +0 -0
  22. package/dist/esm/index.d.ts.map +1 -1
  23. package/dist/esm/services/_zod-issue-formatting.d.ts.map +1 -1
  24. package/dist/esm/services/index.d.ts.map +1 -1
  25. package/dist/esm/services/lockfile-repair.service.d.ts +8 -23
  26. package/dist/esm/services/lockfile-repair.service.d.ts.map +1 -1
  27. package/dist/esm/services/lockfile-repair.service.js +10 -28
  28. package/dist/esm/services/lockfile-repair.service.js.map +1 -1
  29. package/dist/esm/services/module-adopter.service.d.ts.map +1 -1
  30. package/dist/esm/services/module-packager.service.d.ts.map +1 -1
  31. package/dist/esm/services/provider-materialization-hook.d.ts.map +1 -1
  32. package/dist/esm/services/provider-sync-runner.d.ts.map +1 -1
  33. package/dist/esm/services/registry-companion-client.d.ts +26 -4
  34. package/dist/esm/services/registry-companion-client.d.ts.map +1 -1
  35. package/dist/esm/services/registry-companion-client.js +15 -1
  36. package/dist/esm/services/registry-companion-client.js.map +1 -1
  37. package/dist/esm/services/registry-lockfile.service.d.ts.map +1 -1
  38. package/dist/esm/services/registry-server-client.d.ts.map +1 -1
  39. package/dist/tsconfig.build.tsbuildinfo +1 -1
  40. package/dist/tsconfig.tsbuildinfo +1 -1
  41. package/package.json +2 -2
  42. package/src/__tests__/lockfile-repair.service.test.ts +2 -2
  43. package/src/services/lockfile-repair.service.ts +9 -34
  44. package/src/services/registry-companion-client.ts +40 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wildo-ai/wildo-module-client",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "Module-registry runtime services consumed by wildo-cli and the dev companion (Phase 0.5 skeleton)",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Wildo AI",
@@ -30,7 +30,7 @@
30
30
  "test:watch": "vitest"
31
31
  },
32
32
  "dependencies": {
33
- "@wildo-ai/platform-config-lib": "1.1.4"
33
+ "@wildo-ai/platform-config-lib": "1.1.5"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^24.0.15",
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Phase 2 tests for `LockfileRepairService`.
2
+ * Read-only inspector tests for `LockfileRepairService`.
3
3
  *
4
4
  * The service is read-only and produces a structured report.
5
5
  * Tests pin every finding kind:
@@ -7,7 +7,7 @@
7
7
  * - malformed envelope → error finding.
8
8
  * - malformed modules section → error finding.
9
9
  * - lockfile entry pointing at a missing file → warn finding.
10
- * - lockfile entry with non-sha256 digest → warn finding.
10
+ * Malformed-digest dispatch and healthy/structure controls are covered by the CLI repair-contract suite.
11
11
  */
12
12
 
13
13
  import { promises as fs } from 'node:fs';
@@ -1,21 +1,12 @@
1
1
  /**
2
- * `LockfileRepairService` — Phase 2 read-only lockfile diagnostics.
2
+ * `LockfileRepairService` — read-only lockfile diagnostics.
3
3
  *
4
- * Backs `wildo registry repair-lockfile` (CLI command lands in a
5
- * later step). The service does NOT mutate the lockfile by
6
- * default — its job is to surface a structured diagnostic the
7
- * operator can act on:
8
- * - validate the canonical envelope shape;
9
- * - validate `sections.modules` against
10
- * `RegistryModulesLockSectionSchema`;
11
- * - report which `installed[*].files` are missing on disk
12
- * (drift between the lockfile and the source tree);
13
- * - report which `installed[*].artifactDigest` strings are not
14
- * `Sha256DigestSchema`-shaped (residue from pre-tightening
15
- * publishes).
16
- *
17
- * Mutating repair is a Phase 7 deliverable — surfacing the gaps is
18
- * what unblocks the operator now.
4
+ * Backs `wildo registry repair-lockfile`. Strict envelope and module-section
5
+ * validation runs before file inspection. Malformed records, including invalid
6
+ * artifact digests, require restoration from a trusted record; they are never
7
+ * admitted into the automatic repair path. Valid records can report missing
8
+ * source files, which the CLI can re-fetch at their recorded exact version.
9
+ * This inspector does not mutate files.
19
10
  *
20
11
  * `i18n` validation is intentionally NOT performed here (KD-15 +
21
12
  * Review-pass-2 / MEDIUM-5): repair is the wrong place to
@@ -30,7 +21,6 @@ import { z } from 'zod';
30
21
  import { formatZodIssuesAsSingleLine } from './_zod-issue-formatting';
31
22
  import {
32
23
  RegistryModulesLockSectionSchema,
33
- Sha256DigestSchema,
34
24
  getWildoSaasLockPath,
35
25
  type RegistryModulesLockEntry,
36
26
  type RegistryModulesLockSection,
@@ -66,12 +56,6 @@ export type LockfileRepairFinding =
66
56
  kind: 'module-file-missing';
67
57
  moduleId: string;
68
58
  filePath: string;
69
- }
70
- | {
71
- severity: 'warn';
72
- kind: 'module-digest-not-sha256';
73
- moduleId: string;
74
- observedDigest: string;
75
59
  };
76
60
 
77
61
  export interface LockfileRepairReport {
@@ -163,7 +147,7 @@ export const LockfileRepairService = {
163
147
  findings.push({
164
148
  severity: 'error',
165
149
  kind: 'modules-section-malformed',
166
- message: '`sections.modules` failed schema validation.',
150
+ message: '`sections.modules` failed schema validation. Restore the affected record from a trusted lockfile revision; automatic repair does not infer missing or invalid metadata.',
167
151
  detail: formatZodIssuesAsSingleLine(parsed.error),
168
152
  });
169
153
  return { lockfilePath, ok: false, findings };
@@ -179,8 +163,7 @@ export const LockfileRepairService = {
179
163
  },
180
164
 
181
165
  /**
182
- * Per-entry diagnostic helper. Exposed so Phase 7 mutating-
183
- * repair flows can reuse the same predicates.
166
+ * Missing-file diagnostics for an entry already validated by the strict section schema.
184
167
  */
185
168
  async collectEntryFindings(
186
169
  saasRoot: string,
@@ -188,14 +171,6 @@ export const LockfileRepairService = {
188
171
  entry: RegistryModulesLockEntry,
189
172
  findings: LockfileRepairFinding[],
190
173
  ): Promise<void> {
191
- if (!Sha256DigestSchema.safeParse(entry.artifactDigest).success) {
192
- findings.push({
193
- severity: 'warn',
194
- kind: 'module-digest-not-sha256',
195
- moduleId,
196
- observedDigest: entry.artifactDigest,
197
- });
198
- }
199
174
  for (const filePath of entry.files) {
200
175
  const abs = path.resolve(saasRoot, filePath);
201
176
  if (!(await fileExists(abs))) {
@@ -13,6 +13,10 @@
13
13
  * `platform/factory/wildo-dev-companion/src/companion-api/controllers/`)
14
14
  * implements them with the actual ts-morph + filesystem work in
15
15
  * Phase 5+.
16
+ *
17
+ * The four mutations are GATED: the companion refuses any non-`GET` route that does not present the
18
+ * machine-local token, so they take `RegistryCompanionMutationOptions` and `ping` — a `GET` — does
19
+ * not. See that type for why the credential is required rather than optional.
16
20
  */
17
21
 
18
22
  import {
@@ -31,20 +35,50 @@ import { formatZodIssuesAsSingleLine } from './_zod-issue-formatting';
31
35
 
32
36
  const DIAGNOSTIC_LABEL = 'Companion registry';
33
37
 
38
+ /**
39
+ * The header the companion's P-29b token floor reads on a mutating route.
40
+ *
41
+ * A wire contract between two processes that share no package, so it is named at both ends rather
42
+ * than at neither. Its server twin is `COMPANION_TOKEN_HEADER` in the companion's
43
+ * `core/auth/companion-auth-floor.companion.service.ts`; the CLI's is in
44
+ * `wildo-cli/src/services/companion/companion-local-token.utils.ts`. Move one, move all three.
45
+ */
46
+ // semantic-literal-boundary: private companion HTTP protocol, translated only at this client edge.
47
+ const COMPANION_TOKEN_HEADER = 'x-wildo-companion-token';
48
+
34
49
  export interface RegistryCompanionClientOptions {
35
50
  baseUrl: string;
36
51
  timeoutMs?: number;
37
52
  }
38
53
 
54
+ /**
55
+ * What a MUTATING companion registry call needs, over and above an address.
56
+ *
57
+ * `companionToken` is REQUIRED, and that is the whole point of this second type. Every non-`GET`
58
+ * route under `/api/companion/**` is refused without it, and the four methods below have no caller
59
+ * yet (the routes answer a not-implemented envelope until Phase 5) — so making it required now costs
60
+ * nothing and means the caller Phase 5 writes cannot be written without the credential. An optional
61
+ * field would have been a rule to remember; a required one is a compile error.
62
+ *
63
+ * The value is the content of `<appRoot>/.wildo-saas/state/companion.token` (mode 0600), which the
64
+ * companion mints on every boot. This package has no notion of an application root, so reading it is
65
+ * deliberately the caller's job: `wildo-cli` already owns a hardened no-follow reader
66
+ * (`readCompanionTokenNoFollow`), and a second copy of a permission-checked read is precisely where
67
+ * the checks quietly diverge.
68
+ */
69
+ export interface RegistryCompanionMutationOptions extends RegistryCompanionClientOptions {
70
+ companionToken: string;
71
+ }
72
+
39
73
  async function postJson<R>(
40
- options: RegistryCompanionClientOptions,
74
+ options: RegistryCompanionMutationOptions,
41
75
  routePath: string,
42
76
  body: unknown,
43
77
  ): Promise<R> {
44
78
  const url = joinUrl(options.baseUrl, routePath);
45
79
  const res = await fetchWithTimeout(url, {
46
80
  method: 'POST',
47
- headers: { 'content-type': 'application/json' },
81
+ headers: { 'content-type': 'application/json', [COMPANION_TOKEN_HEADER]: options.companionToken },
48
82
  body: JSON.stringify(body),
49
83
  timeoutMs: options.timeoutMs,
50
84
  diagnosticLabel: DIAGNOSTIC_LABEL,
@@ -103,7 +137,7 @@ export const RegistryCompanionClient = {
103
137
  * `sections.modules`, run provider sync.
104
138
  */
105
139
  async install(
106
- options: RegistryCompanionClientOptions,
140
+ options: RegistryCompanionMutationOptions,
107
141
  request: RegistryInstallRequest,
108
142
  ): Promise<RegistryRouteResult> {
109
143
  const raw = await postJson<unknown>(options, REGISTRY_COMPANION_ROUTES.install, request);
@@ -111,7 +145,7 @@ export const RegistryCompanionClient = {
111
145
  },
112
146
 
113
147
  async update(
114
- options: RegistryCompanionClientOptions,
148
+ options: RegistryCompanionMutationOptions,
115
149
  request: RegistryUpdateRequest,
116
150
  ): Promise<RegistryRouteResult> {
117
151
  const raw = await postJson<unknown>(options, REGISTRY_COMPANION_ROUTES.update, request);
@@ -119,7 +153,7 @@ export const RegistryCompanionClient = {
119
153
  },
120
154
 
121
155
  async remove(
122
- options: RegistryCompanionClientOptions,
156
+ options: RegistryCompanionMutationOptions,
123
157
  request: RegistryRemoveRequest,
124
158
  ): Promise<RegistryRouteResult> {
125
159
  const raw = await postJson<unknown>(options, REGISTRY_COMPANION_ROUTES.remove, request);
@@ -127,7 +161,7 @@ export const RegistryCompanionClient = {
127
161
  },
128
162
 
129
163
  async publish(
130
- options: RegistryCompanionClientOptions,
164
+ options: RegistryCompanionMutationOptions,
131
165
  request: RegistryPublishRequest,
132
166
  ): Promise<RegistryRouteResult> {
133
167
  const raw = await postJson<unknown>(options, REGISTRY_COMPANION_ROUTES.publish, request);