@homeflare/alchemy 0.4.1 → 0.5.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 (47) hide show
  1. package/README.md +57 -0
  2. package/dist/openbao/approle-login-form.d.ts +72 -0
  3. package/dist/openbao/approle-login-form.d.ts.map +1 -0
  4. package/dist/openbao/approle-login-result.d.ts +39 -0
  5. package/dist/openbao/approle-login-result.d.ts.map +1 -0
  6. package/dist/openbao/approle-login.d.ts +77 -0
  7. package/dist/openbao/approle-login.d.ts.map +1 -0
  8. package/dist/openbao/bao-http.d.ts +2 -0
  9. package/dist/openbao/bao-http.d.ts.map +1 -1
  10. package/dist/openbao/index.d.ts +7 -0
  11. package/dist/openbao/index.d.ts.map +1 -1
  12. package/dist/openbao/index.js +589 -305
  13. package/dist/openbao/index.js.map +16 -8
  14. package/dist/openbao/mount-path.d.ts +14 -0
  15. package/dist/openbao/mount-path.d.ts.map +1 -0
  16. package/dist/openbao/plugin-form.d.ts +60 -0
  17. package/dist/openbao/plugin-form.d.ts.map +1 -0
  18. package/dist/openbao/plugin-reconcile.d.ts +18 -0
  19. package/dist/openbao/plugin-reconcile.d.ts.map +1 -0
  20. package/dist/openbao/plugin-wire.d.ts +45 -0
  21. package/dist/openbao/plugin-wire.d.ts.map +1 -0
  22. package/dist/openbao/plugin.d.ts +31 -0
  23. package/dist/openbao/plugin.d.ts.map +1 -0
  24. package/dist/openbao/ssh-role-form.d.ts +6 -5
  25. package/dist/openbao/ssh-role-form.d.ts.map +1 -1
  26. package/dist/openbao/ssh-role.d.ts.map +1 -1
  27. package/package.json +1 -1
  28. package/src/openbao/approle-login-form.test.ts +64 -0
  29. package/src/openbao/approle-login-form.ts +153 -0
  30. package/src/openbao/approle-login-result.ts +96 -0
  31. package/src/openbao/approle-login.test.ts +200 -0
  32. package/src/openbao/approle-login.ts +156 -0
  33. package/src/openbao/auth-role-form.test.ts +42 -0
  34. package/src/openbao/bao-http.ts +2 -0
  35. package/src/openbao/index.ts +13 -0
  36. package/src/openbao/mount-path.test.ts +23 -0
  37. package/src/openbao/mount-path.ts +25 -0
  38. package/src/openbao/mount-wire.test.ts +13 -0
  39. package/src/openbao/plugin-form.test.ts +86 -0
  40. package/src/openbao/plugin-form.ts +164 -0
  41. package/src/openbao/plugin-reconcile.ts +92 -0
  42. package/src/openbao/plugin-wire.test.ts +146 -0
  43. package/src/openbao/plugin-wire.ts +65 -0
  44. package/src/openbao/plugin.ts +100 -0
  45. package/src/openbao/ssh-role-form.test.ts +105 -0
  46. package/src/openbao/ssh-role-form.ts +18 -16
  47. package/src/openbao/ssh-role.ts +3 -4
@@ -13,6 +13,7 @@
13
13
  */
14
14
  import { sha256 } from './digest.ts';
15
15
  import { parseDuration, ttlSeconds } from './mount-form.ts';
16
+ import { sshMountOf as mountOf } from './mount-path.ts';
16
17
 
17
18
  export interface BaoSshRoleProps {
18
19
  /** Role name, as `<mount>/roles/{name}` takes it. */
@@ -76,8 +77,7 @@ export interface BaoSshRoleAttributes extends Omit<BaoSshRoleForm, 'maxTtl' | 't
76
77
  digest: string;
77
78
  }
78
79
 
79
- /** Mount path without a trailing slash; `ssh` when the caller did not say. */
80
- export const mountOf = (mount: string | undefined) => (mount ?? 'ssh').replace(/\/+$/, '');
80
+ export { mountOf };
81
81
 
82
82
  export const readPath = (mount: string | undefined, name: string) =>
83
83
  `${mountOf(mount)}/roles/${name}`;
@@ -159,26 +159,28 @@ export const attributesOf = (
159
159
  };
160
160
 
161
161
  /**
162
- * ⛔ THE MAPS CROSS THE WIRE AS A JSON STRING, AND THAT IS THE CORRECT SHAPE. MEASURED with
163
- * `bao write -output-curl-string` against the live v2.6.2 (no write was sent): the CLI
164
- * puts every `k=v` value in the body as a string, so `default_extensions` leaves as
165
- * `"{\"permit-pty\":\"\"}"` and never as an object. OpenBao's own OpenAPI types that field
166
- * `object`/`format: map` — a `framework` TypeMap, which JSON-decodes a string value.
167
- * ⚠️ THAT DECODE IS REASONED, NOT MEASURED: writing to the live engine was out of bounds,
168
- * so the round trip was never executed. If a first deploy lands a role whose
169
- * default_extensions came out EMPTY, this is the line that was wrong, and the fix is to
170
- * send the map as a JSON object in writeBody rather than as this string — the HTTP body
171
- * can now carry either.
162
+ * ⛔ THE MAPS CROSS THE WIRE AS JSON OBJECTS. A JSON STRING IS REJECTED, SO EVERY WRITE FAILED.
163
+ * History: `bao write -output-curl-string` showed the CLI sending `k=v` values as strings,
164
+ * so this once sent `"{\"permit-pty\":\"\"}"` on the reasoning that a `framework` TypeMap
165
+ * JSON-decodes a string. ⚠️ IT DOES NOT. MEASURED 2026-09-21 against sdk v2.6.2 itself (a Go
166
+ * probe of framework.FieldData.Validate, no server): TypeMap is `mapstructure.WeakDecode`
167
+ * (framework/field_data.go:271-276), which refuses a string with "expected type
168
+ * 'map[string]interface {}', got unconvertible type 'string'" — and framework/backend.go:
169
+ * 281-285 answers that with a 400 before the handler runs. `"{}"` fails the same way, so every
170
+ * Bao.SshRole write, not only those with extensions, would have been refused. It went unseen
171
+ * because the adopted roles already matched and no write was ever sent. The same probe
172
+ * accepted the object form and every other field of writeBody as sent.
172
173
  */
173
- const mapValue = (map: Readonly<Record<string, string>>) => JSON.stringify(extMap(map));
174
+ const mapValue = (map: Readonly<Record<string, string>>) => extMap(map);
174
175
 
175
176
  /**
176
177
  * ⛔ EVERY MANAGED FIELD IS SENT ON EVERY WRITE, INCLUDING THE FALSE ONES. The role write is
177
178
  * a full replace (see ssh-role.ts), so an omitted field is not "left alone" — it is reset.
178
- * Sending the resolved form makes the body and the declaration the same statement. All
179
- * strings, exactly the `k=v` pairs `bao write` sent, for `PUT <mount>/roles/<name>`.
179
+ * Sending the resolved form makes the body and the declaration the same statement. Strings,
180
+ * exactly the `k=v` pairs `bao write` sent, for `PUT <mount>/roles/<name>` — except the two
181
+ * maps, which must be objects (the ⛔ on mapValue).
180
182
  */
181
- export const writeBody = (form: BaoSshRoleForm): Record<string, string> => ({
183
+ export const writeBody = (form: BaoSshRoleForm): Record<string, unknown> => ({
182
184
  key_type: 'ca',
183
185
  allowed_users: form.allowedUsers.join(','),
184
186
  default_user: form.defaultUser,
@@ -209,10 +209,9 @@ export const BaoSshRoleProvider = () =>
209
209
  yield* baoWrite('PUT', path, writeBody(form));
210
210
  }
211
211
  /**
212
- * ⚠️ RE-READ RATHER THAN ECHO THE DECLARATION. The write is the only place the
213
- * JSON-string encoding of `default_extensions` could be wrong (see the ⛔ on
214
- * mapValue), and a provider that returned its own props would record a role it
215
- * had never confirmed.
212
+ * ⚠️ RE-READ RATHER THAN ECHO THE DECLARATION. The map encoding in the write was
213
+ * wrong once already, unseen until 2026-09-21 (the ⛔ on mapValue), and a provider
214
+ * that returned its own props would record a role it had never confirmed.
216
215
  */
217
216
  const after = yield* readRole(form);
218
217
  if (after === undefined) {