@homeflare/distilled-openbao 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/credentials.d.ts +3 -2
- package/dist/credentials.d.ts.map +1 -1
- package/dist/credentials.js +5 -3
- package/dist/credentials.js.map +1 -1
- package/dist/errors.d.ts +2 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/protocol-requests.test.d.ts +2 -0
- package/dist/protocol-requests.test.d.ts.map +1 -0
- package/dist/protocol-requests.test.js +32 -0
- package/dist/protocol-requests.test.js.map +1 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +9 -4
- package/dist/protocol.js.map +1 -1
- package/dist/retry.d.ts +4 -5
- package/dist/retry.d.ts.map +1 -1
- package/dist/retry.js +4 -5
- package/dist/retry.js.map +1 -1
- package/package.json +1 -1
- package/src/credentials.ts +9 -5
- package/src/errors.ts +4 -2
- package/src/protocol-requests.test.ts +66 -0
- package/src/protocol.ts +9 -4
- package/src/retry.ts +4 -5
package/dist/credentials.d.ts
CHANGED
|
@@ -12,7 +12,8 @@ export declare const API_PATH = "/v1";
|
|
|
12
12
|
/** Normalize an address (or an already-complete `/v1` root) into the API base URL. */
|
|
13
13
|
export declare const normalizeBaseUrl: (addr: string) => string;
|
|
14
14
|
export interface Config {
|
|
15
|
-
|
|
15
|
+
/** Absent for a local agent listener that supplies its own identity. */
|
|
16
|
+
readonly token?: Redacted.Redacted<string>;
|
|
16
17
|
/** Fully-qualified API root, e.g. `http://127.0.0.1:8200/v1`. */
|
|
17
18
|
readonly apiBaseUrl: string;
|
|
18
19
|
/** `X-Vault-Namespace`, when the estate uses one. Absent = root namespace. */
|
|
@@ -24,7 +25,7 @@ export declare class Credentials extends Credentials_base {
|
|
|
24
25
|
export declare const CredentialsFromEnv: Layer.Layer<Credentials, never, never>;
|
|
25
26
|
/** Convenience layer from a plain token, address and optional namespace. */
|
|
26
27
|
export declare const credentials: (config: {
|
|
27
|
-
readonly token
|
|
28
|
+
readonly token?: string | Redacted.Redacted<string>;
|
|
28
29
|
readonly addr: string;
|
|
29
30
|
readonly namespace?: string;
|
|
30
31
|
}) => Layer.Layer<Credentials>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAG5C;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAc9B,sFAAsF;AACtF,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,MAG/C,CAAC;AAEF,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAG5C;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAc9B,sFAAsF;AACtF,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,MAG/C,CAAC;AAEF,MAAM,WAAW,MAAM;IACrB,wEAAwE;IACxE,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3C,iEAAiE;IACjE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;;AAED,qBAAa,WAAY,SAAQ,gBAGR;CAAG;AAQ5B,eAAO,MAAM,kBAAkB,wCAmB9B,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,WAAW,WAAY;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,KAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAWxB,CAAC"}
|
package/dist/credentials.js
CHANGED
|
@@ -44,14 +44,16 @@ export const normalizeBaseUrl = (addr) => {
|
|
|
44
44
|
export class Credentials extends Context.Service()("OpenBaoCredentials") {
|
|
45
45
|
}
|
|
46
46
|
const envConfig = EffectConfig.all({
|
|
47
|
-
token: EffectConfig.String("BAO_TOKEN"),
|
|
47
|
+
token: EffectConfig.String("BAO_TOKEN").pipe(EffectConfig.option),
|
|
48
48
|
addr: EffectConfig.String("BAO_ADDR"),
|
|
49
49
|
namespace: EffectConfig.String("BAO_NAMESPACE").pipe(EffectConfig.option),
|
|
50
50
|
});
|
|
51
51
|
export const CredentialsFromEnv = Layer.succeed(Credentials, envConfig.pipe(Effect.mapError(() => new ConfigError({
|
|
52
|
-
message: "BAO_ADDR
|
|
52
|
+
message: "BAO_ADDR environment variable is required",
|
|
53
53
|
})), Effect.map(({ token, addr, namespace }) => ({
|
|
54
|
-
token:
|
|
54
|
+
token: token.valueOrUndefined === undefined
|
|
55
|
+
? undefined
|
|
56
|
+
: Redacted.make(token.valueOrUndefined),
|
|
55
57
|
apiBaseUrl: normalizeBaseUrl(addr),
|
|
56
58
|
namespace: namespace.valueOrUndefined,
|
|
57
59
|
})), Effect.orDie));
|
package/dist/credentials.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,YAAY,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG,CAAC,IAAY,EAAU,EAAE;IACnD,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC;IACtB,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,CAAC;IACzD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC,CAAC;AAEF,sFAAsF;AACtF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAU,EAAE;IACvD,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,QAAQ,EAAE,CAAC;AACxE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,YAAY,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG,CAAC,IAAY,EAAU,EAAE;IACnD,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC;IACtB,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,CAAC;IACzD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC,CAAC;AAEF,sFAAsF;AACtF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAU,EAAE;IACvD,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,QAAQ,EAAE,CAAC;AACxE,CAAC,CAAC;AAWF,MAAM,OAAO,WAAY,SAAQ,OAAO,CAAC,OAAO,EAG7C,CAAC,oBAAoB,CAAC;CAAG;AAE5B,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC;IACjC,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;IACjE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC;IACrC,SAAS,EAAE,YAAY,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;CAC1E,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC,OAAO,CAC7C,WAAW,EACX,SAAS,CAAC,IAAI,CACZ,MAAM,CAAC,QAAQ,CACb,GAAG,EAAE,CACH,IAAI,WAAW,CAAC;IACd,OAAO,EAAE,2CAA2C;CACrD,CAAC,CACL,EACD,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1C,KAAK,EACH,KAAK,CAAC,gBAAgB,KAAK,SAAS;QAClC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC;IAC3C,UAAU,EAAE,gBAAgB,CAAC,IAAI,CAAC;IAClC,SAAS,EAAE,SAAS,CAAC,gBAAgB;CACtC,CAAC,CAAC,EACH,MAAM,CAAC,KAAK,CACb,CACF,CAAC;AAEF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAI3B,EAA4B,EAAE,CAC7B,KAAK,CAAC,OAAO,CACX,WAAW,EACX,MAAM,CAAC,OAAO,CAAC;IACb,KAAK,EACH,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ;QAC9B,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QAC7B,CAAC,CAAC,MAAM,CAAC,KAAK;IAClB,UAAU,EAAE,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC,SAAS;CAC5B,CAAC,CACH,CAAC"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* status (and message, when OpenBao supplies one) under `patches/`.
|
|
17
17
|
*/
|
|
18
18
|
export { BadGateway, BadRequest, Conflict, ConfigError, Forbidden, GatewayTimeout, InternalServerError, Locked, NotFound, ServiceUnavailable, TooManyRequests, Unauthorized, UnprocessableEntity, HTTP_STATUS_MAP, DEFAULT_ERRORS, API_ERRORS, } from "@distilled.cloud/core/errors";
|
|
19
|
-
import type {
|
|
19
|
+
import type { API_ERRORS } from "@distilled.cloud/core/errors";
|
|
20
20
|
import * as Schema from "effect/Schema";
|
|
21
21
|
declare const UnknownOpenBaoError_base: Schema.Class<UnknownOpenBaoError, Schema.TaggedStruct<"UnknownOpenBaoError", {
|
|
22
22
|
readonly code: Schema.optional<Schema.String>;
|
|
@@ -53,5 +53,5 @@ export type ClientErrors = UnknownOpenBaoError | OpenBaoParseError;
|
|
|
53
53
|
* Default OpenBao operation errors: the shared HTTP status errors from core
|
|
54
54
|
* plus the client-level fallback/decode errors.
|
|
55
55
|
*/
|
|
56
|
-
export type DefaultErrors =
|
|
56
|
+
export type DefaultErrors = InstanceType<(typeof API_ERRORS)[number]> | ClientErrors;
|
|
57
57
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,MAAM,EACN,QAAQ,EACR,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,UAAU,GACX,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,MAAM,EACN,QAAQ,EACR,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,UAAU,GACX,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;;;;;;;;;;AAGxC;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,wBAOT;CAAG;;;;;;;;;AAEnC,kCAAkC;AAClC,qBAAa,iBAAkB,SAAQ,sBAMR;CAAG;AAElC;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,mBAAmB,GAAG,iBAAiB,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB,YAAY,CAAC,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,GACzC,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-requests.test.d.ts","sourceRoot":"","sources":["../src/protocol-requests.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
5
|
+
import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse";
|
|
6
|
+
import { credentials } from "./credentials.js";
|
|
7
|
+
import * as Retry from "./retry.js";
|
|
8
|
+
import { policiesDeleteAclPolicy } from "./services/policies.js";
|
|
9
|
+
for (const token of [undefined, "", "test-token"]) {
|
|
10
|
+
test(`agent request header is present; ${token ? "nonempty" : "absent or empty"} token has correct header semantics`, async () => {
|
|
11
|
+
const client = HttpClient.make((request) => {
|
|
12
|
+
expect(request.headers["x-vault-request"]).toBe("true");
|
|
13
|
+
if (token)
|
|
14
|
+
expect(request.headers["x-vault-token"]).toBe(token);
|
|
15
|
+
else
|
|
16
|
+
expect(request.headers["x-vault-token"]).toBeUndefined();
|
|
17
|
+
expect(request.headers["x-vault-namespace"]).toBeUndefined();
|
|
18
|
+
return Effect.succeed(HttpClientResponse.fromWeb(request, new Response(null, { status: 204 })));
|
|
19
|
+
});
|
|
20
|
+
await Effect.runPromise(policiesDeleteAclPolicy({ name: "test" }).pipe(Retry.none, Effect.provide(Layer.mergeAll(Layer.succeed(HttpClient.HttpClient, client), credentials({ addr: "http://fake.invalid", token })))));
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
test("every status mapped by the protocol is represented in the operation error union", async () => {
|
|
24
|
+
// These catchTag calls must compile: core DEFAULT_ERRORS excludes both tags,
|
|
25
|
+
// but OpenBaoProtocol's default HTTP_STATUS_MAP emits them for every operation.
|
|
26
|
+
for (const status of [403, 404]) {
|
|
27
|
+
const client = HttpClient.make((request) => Effect.succeed(HttpClientResponse.fromWeb(request, Response.json({ errors: [] }, { status }))));
|
|
28
|
+
const tag = await Effect.runPromise(policiesDeleteAclPolicy({ name: "test" }).pipe(Retry.none, Effect.as("success"), Effect.catchTag("Forbidden", () => Effect.succeed("Forbidden")), Effect.catchTag("NotFound", () => Effect.succeed("NotFound")), Effect.provide(Layer.mergeAll(Layer.succeed(HttpClient.HttpClient, client), credentials({ addr: "http://fake.invalid", token: "test-token" })))));
|
|
29
|
+
expect(tag).toBe(status === 403 ? "Forbidden" : "NotFound");
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
//# sourceMappingURL=protocol-requests.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-requests.test.js","sourceRoot":"","sources":["../src/protocol-requests.test.ts"],"names":[],"mappings":"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"}
|
package/dist/protocol.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AA2CA,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,KAAK,UAAU,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,KAAK,eAAe,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,KAAK,GAAG,MAAM,2BAA2B,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAKhE,OAAO,EAAE,WAAW,EAAe,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEtE;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,WAAW,GACX,eAAe,CAAC,eAAe,CAAC;AAEpC,0EAA0E;AAC1E,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,UAAU,CAAC,UAAU,CAAC;AAyBnE,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CA+BlD,CAAC"}
|
package/dist/protocol.js
CHANGED
|
@@ -31,9 +31,11 @@
|
|
|
31
31
|
* match on status, or on message when OpenBao actually supplies one — see
|
|
32
32
|
* `patches/`.
|
|
33
33
|
*
|
|
34
|
-
* Authentication is
|
|
35
|
-
*
|
|
36
|
-
*
|
|
34
|
+
* Authentication is `X-Vault-Token` when a credential carries a nonempty
|
|
35
|
+
* token; omit it for a local agent that supplies its own identity. An
|
|
36
|
+
* optional `X-Vault-Namespace` selects a namespace; absent means root.
|
|
37
|
+
* `X-Vault-Request: true` admits agent listeners with require_request_header
|
|
38
|
+
* (OpenBao v2.6.2 command/agent.go:544-548). A namespace does not change a mounted
|
|
37
39
|
* backend's own path shape (see `stacks/distilled-submodules/spec-repos/
|
|
38
40
|
* openbao/fetch-specs.ts`'s module docs for how that was confirmed), so it
|
|
39
41
|
* is purely a request header here, never a path segment.
|
|
@@ -77,7 +79,10 @@ export const OpenBaoProtocol = makeRestProtocol({
|
|
|
77
79
|
}),
|
|
78
80
|
baseUrl: (creds) => creds.apiBaseUrl,
|
|
79
81
|
headers: (creds) => ({
|
|
80
|
-
|
|
82
|
+
...(creds.token && Redacted.value(creds.token) !== ""
|
|
83
|
+
? { "X-Vault-Token": Redacted.value(creds.token) }
|
|
84
|
+
: {}),
|
|
85
|
+
"X-Vault-Request": "true",
|
|
81
86
|
...(creds.namespace ? { "X-Vault-Namespace": creds.namespace } : {}),
|
|
82
87
|
Accept: "application/json",
|
|
83
88
|
}),
|
package/dist/protocol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
|
package/dist/retry.d.ts
CHANGED
|
@@ -10,11 +10,10 @@
|
|
|
10
10
|
* `packages/alchemy/src/openbao/bao-http.ts` caps in-flight OpenBao
|
|
11
11
|
* exchanges at 8 process-wide (`BaoGate`, a `Semaphore`) after a real
|
|
12
12
|
* outage: unbounded Alchemy fan-out took the dev listener's socket down
|
|
13
|
-
* (measured 2026-09-14). That cap
|
|
14
|
-
*
|
|
15
|
-
* the
|
|
16
|
-
*
|
|
17
|
-
* unchanged to every call this package makes.
|
|
13
|
+
* (measured 2026-09-14). That cap lives inside the kit's call runner, not
|
|
14
|
+
* inside HttpClient. SDK consumers must explicitly share the same gate;
|
|
15
|
+
* merely supplying the HTTP client does not apply it. The kit runner also
|
|
16
|
+
* selects Retry.none so a failed response cannot repeat a sent write.
|
|
18
17
|
*
|
|
19
18
|
* @example
|
|
20
19
|
* ```ts
|
package/dist/retry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,OAAO,MAAM,6BAA6B,CAAC;AAEvD,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;AACtC,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;AACtC,MAAM,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;;AAEpC,uEAAuE;AACvE,qBAAa,KAAM,SAAQ,UAAgD;CAAG;AAE9E,yEAAyE;AACzE,eAAO,MAAM,MAAM,EAAE;IACnB,CACE,OAAO,EAAE,OAAO,GACf,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACT,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5C,CACE,OAAO,EAAE,OAAO,GACf,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACT,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;CAEU,CAAC;AAEzD,sCAAsC;AACtC,eAAO,MAAM,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACzB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAEzC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,OAA6B,CAAC;AAExD,eAAO,MAAM,QAAQ,0JAAmB,CAAC;AACzC,eAAO,MAAM,MAAM,uMAAiB,CAAC;AAErC,mEAAmE;AACnE,eAAO,MAAM,iBAAiB,EAAE,OAAmC,CAAC;AAEpE,0EAA0E;AAC1E,eAAO,MAAM,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAqC,CAAC;AAEhF,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,EAAE,OAAkC,CAAC;AAElE,yEAAyE;AACzE,eAAO,MAAM,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAoC,CAAC"}
|
package/dist/retry.js
CHANGED
|
@@ -10,11 +10,10 @@
|
|
|
10
10
|
* `packages/alchemy/src/openbao/bao-http.ts` caps in-flight OpenBao
|
|
11
11
|
* exchanges at 8 process-wide (`BaoGate`, a `Semaphore`) after a real
|
|
12
12
|
* outage: unbounded Alchemy fan-out took the dev listener's socket down
|
|
13
|
-
* (measured 2026-09-14). That cap
|
|
14
|
-
*
|
|
15
|
-
* the
|
|
16
|
-
*
|
|
17
|
-
* unchanged to every call this package makes.
|
|
13
|
+
* (measured 2026-09-14). That cap lives inside the kit's call runner, not
|
|
14
|
+
* inside HttpClient. SDK consumers must explicitly share the same gate;
|
|
15
|
+
* merely supplying the HTTP client does not apply it. The kit runner also
|
|
16
|
+
* selects Retry.none so a failed response cannot repeat a sent write.
|
|
18
17
|
*
|
|
19
18
|
* @example
|
|
20
19
|
* ```ts
|
package/dist/retry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,OAAO,MAAM,6BAA6B,CAAC;AAMvD,uEAAuE;AACvE,MAAM,OAAO,KAAM,SAAQ,OAAO,CAAC,OAAO,EAAiB,CAAC,cAAc,CAAC;CAAG;AAE9E,yEAAyE;AACzE,MAAM,CAAC,MAAM,MAAM,GAWf,CAAC,gBAAmC,EAAE,EAAE,CAC1C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAEzD,sCAAsC;AACtC,MAAM,CAAC,MAAM,IAAI,GAE6B,MAAM,CAAC,OAAO,CAC1D,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,CAC7C,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAY,OAAO,CAAC,WAAW,CAAC;AAExD,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;AACzC,MAAM,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;AAErC,mEAAmE;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAAY,OAAO,CAAC,iBAAiB,CAAC;AAEpE,0EAA0E;AAC1E,MAAM,CAAC,MAAM,UAAU,GAEuB,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEhF,kEAAkE;AAClE,MAAM,CAAC,MAAM,gBAAgB,GAAY,OAAO,CAAC,gBAAgB,CAAC;AAElE,yEAAyE;AACzE,MAAM,CAAC,MAAM,SAAS,GAEwB,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homeflare/distilled-openbao",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Interim npm home for @distilled.cloud/openbao — see docs/distilled-interim.md. Not published upstream yet; the kit aliases @distilled.cloud/openbao onto this package until it is.",
|
|
5
5
|
"homepage": "https://github.com/taslabs-net/homeflare-kit/tree/main/packages/distilled-openbao#readme",
|
|
6
6
|
"bugs": "https://github.com/taslabs-net/homeflare-kit/issues",
|
package/src/credentials.ts
CHANGED
|
@@ -45,7 +45,8 @@ export const normalizeBaseUrl = (addr: string): string => {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
export interface Config {
|
|
48
|
-
|
|
48
|
+
/** Absent for a local agent listener that supplies its own identity. */
|
|
49
|
+
readonly token?: Redacted.Redacted<string>;
|
|
49
50
|
/** Fully-qualified API root, e.g. `http://127.0.0.1:8200/v1`. */
|
|
50
51
|
readonly apiBaseUrl: string;
|
|
51
52
|
/** `X-Vault-Namespace`, when the estate uses one. Absent = root namespace. */
|
|
@@ -58,7 +59,7 @@ export class Credentials extends Context.Service<
|
|
|
58
59
|
>()("OpenBaoCredentials") {}
|
|
59
60
|
|
|
60
61
|
const envConfig = EffectConfig.all({
|
|
61
|
-
token: EffectConfig.String("BAO_TOKEN"),
|
|
62
|
+
token: EffectConfig.String("BAO_TOKEN").pipe(EffectConfig.option),
|
|
62
63
|
addr: EffectConfig.String("BAO_ADDR"),
|
|
63
64
|
namespace: EffectConfig.String("BAO_NAMESPACE").pipe(EffectConfig.option),
|
|
64
65
|
});
|
|
@@ -69,11 +70,14 @@ export const CredentialsFromEnv = Layer.succeed(
|
|
|
69
70
|
Effect.mapError(
|
|
70
71
|
() =>
|
|
71
72
|
new ConfigError({
|
|
72
|
-
message: "BAO_ADDR
|
|
73
|
+
message: "BAO_ADDR environment variable is required",
|
|
73
74
|
}),
|
|
74
75
|
),
|
|
75
76
|
Effect.map(({ token, addr, namespace }) => ({
|
|
76
|
-
token:
|
|
77
|
+
token:
|
|
78
|
+
token.valueOrUndefined === undefined
|
|
79
|
+
? undefined
|
|
80
|
+
: Redacted.make(token.valueOrUndefined),
|
|
77
81
|
apiBaseUrl: normalizeBaseUrl(addr),
|
|
78
82
|
namespace: namespace.valueOrUndefined,
|
|
79
83
|
})),
|
|
@@ -83,7 +87,7 @@ export const CredentialsFromEnv = Layer.succeed(
|
|
|
83
87
|
|
|
84
88
|
/** Convenience layer from a plain token, address and optional namespace. */
|
|
85
89
|
export const credentials = (config: {
|
|
86
|
-
readonly token
|
|
90
|
+
readonly token?: string | Redacted.Redacted<string>;
|
|
87
91
|
readonly addr: string;
|
|
88
92
|
readonly namespace?: string;
|
|
89
93
|
}): Layer.Layer<Credentials> =>
|
package/src/errors.ts
CHANGED
|
@@ -33,7 +33,7 @@ export {
|
|
|
33
33
|
DEFAULT_ERRORS,
|
|
34
34
|
API_ERRORS,
|
|
35
35
|
} from "@distilled.cloud/core/errors";
|
|
36
|
-
import type {
|
|
36
|
+
import type { API_ERRORS } from "@distilled.cloud/core/errors";
|
|
37
37
|
|
|
38
38
|
import * as Schema from "effect/Schema";
|
|
39
39
|
import * as Category from "@distilled.cloud/core/category";
|
|
@@ -70,4 +70,6 @@ export type ClientErrors = UnknownOpenBaoError | OpenBaoParseError;
|
|
|
70
70
|
* Default OpenBao operation errors: the shared HTTP status errors from core
|
|
71
71
|
* plus the client-level fallback/decode errors.
|
|
72
72
|
*/
|
|
73
|
-
export type DefaultErrors =
|
|
73
|
+
export type DefaultErrors =
|
|
74
|
+
| InstanceType<(typeof API_ERRORS)[number]>
|
|
75
|
+
| ClientErrors;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
5
|
+
import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse";
|
|
6
|
+
import { credentials } from "./credentials.ts";
|
|
7
|
+
import * as Retry from "./retry.ts";
|
|
8
|
+
import { policiesDeleteAclPolicy } from "./services/policies.ts";
|
|
9
|
+
|
|
10
|
+
for (const token of [undefined, "", "test-token"]) {
|
|
11
|
+
test(`agent request header is present; ${token ? "nonempty" : "absent or empty"} token has correct header semantics`, async () => {
|
|
12
|
+
const client = HttpClient.make((request) => {
|
|
13
|
+
expect(request.headers["x-vault-request"]).toBe("true");
|
|
14
|
+
if (token) expect(request.headers["x-vault-token"]).toBe(token);
|
|
15
|
+
else expect(request.headers["x-vault-token"]).toBeUndefined();
|
|
16
|
+
expect(request.headers["x-vault-namespace"]).toBeUndefined();
|
|
17
|
+
return Effect.succeed(
|
|
18
|
+
HttpClientResponse.fromWeb(
|
|
19
|
+
request,
|
|
20
|
+
new Response(null, { status: 204 }),
|
|
21
|
+
),
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
await Effect.runPromise(
|
|
25
|
+
policiesDeleteAclPolicy({ name: "test" }).pipe(
|
|
26
|
+
Retry.none,
|
|
27
|
+
Effect.provide(
|
|
28
|
+
Layer.mergeAll(
|
|
29
|
+
Layer.succeed(HttpClient.HttpClient, client),
|
|
30
|
+
credentials({ addr: "http://fake.invalid", token }),
|
|
31
|
+
),
|
|
32
|
+
),
|
|
33
|
+
),
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
test("every status mapped by the protocol is represented in the operation error union", async () => {
|
|
39
|
+
// These catchTag calls must compile: core DEFAULT_ERRORS excludes both tags,
|
|
40
|
+
// but OpenBaoProtocol's default HTTP_STATUS_MAP emits them for every operation.
|
|
41
|
+
for (const status of [403, 404]) {
|
|
42
|
+
const client = HttpClient.make((request) =>
|
|
43
|
+
Effect.succeed(
|
|
44
|
+
HttpClientResponse.fromWeb(
|
|
45
|
+
request,
|
|
46
|
+
Response.json({ errors: [] }, { status }),
|
|
47
|
+
),
|
|
48
|
+
),
|
|
49
|
+
);
|
|
50
|
+
const tag = await Effect.runPromise(
|
|
51
|
+
policiesDeleteAclPolicy({ name: "test" }).pipe(
|
|
52
|
+
Retry.none,
|
|
53
|
+
Effect.as("success"),
|
|
54
|
+
Effect.catchTag("Forbidden", () => Effect.succeed("Forbidden")),
|
|
55
|
+
Effect.catchTag("NotFound", () => Effect.succeed("NotFound")),
|
|
56
|
+
Effect.provide(
|
|
57
|
+
Layer.mergeAll(
|
|
58
|
+
Layer.succeed(HttpClient.HttpClient, client),
|
|
59
|
+
credentials({ addr: "http://fake.invalid", token: "test-token" }),
|
|
60
|
+
),
|
|
61
|
+
),
|
|
62
|
+
),
|
|
63
|
+
);
|
|
64
|
+
expect(tag).toBe(status === 403 ? "Forbidden" : "NotFound");
|
|
65
|
+
}
|
|
66
|
+
});
|
package/src/protocol.ts
CHANGED
|
@@ -31,9 +31,11 @@
|
|
|
31
31
|
* match on status, or on message when OpenBao actually supplies one — see
|
|
32
32
|
* `patches/`.
|
|
33
33
|
*
|
|
34
|
-
* Authentication is
|
|
35
|
-
*
|
|
36
|
-
*
|
|
34
|
+
* Authentication is `X-Vault-Token` when a credential carries a nonempty
|
|
35
|
+
* token; omit it for a local agent that supplies its own identity. An
|
|
36
|
+
* optional `X-Vault-Namespace` selects a namespace; absent means root.
|
|
37
|
+
* `X-Vault-Request: true` admits agent listeners with require_request_header
|
|
38
|
+
* (OpenBao v2.6.2 command/agent.go:544-548). A namespace does not change a mounted
|
|
37
39
|
* backend's own path shape (see `stacks/distilled-submodules/spec-repos/
|
|
38
40
|
* openbao/fetch-specs.ts`'s module docs for how that was confirmed), so it
|
|
39
41
|
* is purely a request header here, never a path segment.
|
|
@@ -100,7 +102,10 @@ export const OpenBaoProtocol: Layer.Layer<API.Protocol> =
|
|
|
100
102
|
}),
|
|
101
103
|
baseUrl: (creds) => creds.apiBaseUrl,
|
|
102
104
|
headers: (creds) => ({
|
|
103
|
-
|
|
105
|
+
...(creds.token && Redacted.value(creds.token) !== ""
|
|
106
|
+
? { "X-Vault-Token": Redacted.value(creds.token) }
|
|
107
|
+
: {}),
|
|
108
|
+
"X-Vault-Request": "true",
|
|
104
109
|
...(creds.namespace ? { "X-Vault-Namespace": creds.namespace } : {}),
|
|
105
110
|
Accept: "application/json",
|
|
106
111
|
}),
|
package/src/retry.ts
CHANGED
|
@@ -10,11 +10,10 @@
|
|
|
10
10
|
* `packages/alchemy/src/openbao/bao-http.ts` caps in-flight OpenBao
|
|
11
11
|
* exchanges at 8 process-wide (`BaoGate`, a `Semaphore`) after a real
|
|
12
12
|
* outage: unbounded Alchemy fan-out took the dev listener's socket down
|
|
13
|
-
* (measured 2026-09-14). That cap
|
|
14
|
-
*
|
|
15
|
-
* the
|
|
16
|
-
*
|
|
17
|
-
* unchanged to every call this package makes.
|
|
13
|
+
* (measured 2026-09-14). That cap lives inside the kit's call runner, not
|
|
14
|
+
* inside HttpClient. SDK consumers must explicitly share the same gate;
|
|
15
|
+
* merely supplying the HTTP client does not apply it. The kit runner also
|
|
16
|
+
* selects Retry.none so a failed response cannot repeat a sent write.
|
|
18
17
|
*
|
|
19
18
|
* @example
|
|
20
19
|
* ```ts
|