@homeflare/distilled-openbao 0.2.0 → 0.2.2
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/README.md +28 -3
- 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-mount-tables.d.ts +10 -0
- package/dist/protocol-mount-tables.d.ts.map +1 -0
- package/dist/protocol-mount-tables.js +39 -0
- package/dist/protocol-mount-tables.js.map +1 -0
- package/dist/protocol-mount-tables.test.d.ts +2 -0
- package/dist/protocol-mount-tables.test.d.ts.map +1 -0
- package/dist/protocol-mount-tables.test.js +164 -0
- package/dist/protocol-mount-tables.test.js.map +1 -0
- 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 +11 -5
- 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/dist/services/auth.d.ts +46 -1
- package/dist/services/auth.d.ts.map +1 -1
- package/dist/services/auth.js +39 -1
- package/dist/services/auth.js.map +1 -1
- package/dist/services/mounts.d.ts +46 -1
- package/dist/services/mounts.d.ts.map +1 -1
- package/dist/services/mounts.js +39 -1
- package/dist/services/mounts.js.map +1 -1
- package/dist/traits.d.ts +3 -8
- package/dist/traits.d.ts.map +1 -1
- package/dist/traits.js +5 -1
- package/dist/traits.js.map +1 -1
- package/package.json +1 -1
- package/src/credentials.ts +9 -5
- package/src/errors.ts +4 -2
- package/src/protocol-mount-tables.test.ts +190 -0
- package/src/protocol-mount-tables.ts +60 -0
- package/src/protocol-requests.test.ts +66 -0
- package/src/protocol.ts +11 -5
- package/src/retry.ts +4 -5
- package/src/services/auth.ts +96 -2
- package/src/services/mounts.ts +96 -2
- package/src/traits.ts +9 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The auth/mount inventories require a data map (OpenBao v2.6.2
|
|
3
|
+
* vault/logical_system.go:930-959,2108-2134; api/v2 sys_{auth,mounts}.go).
|
|
4
|
+
* A missing envelope must never masquerade as an empty table and authorize
|
|
5
|
+
* a consumer's create. Other logical, health and login shapes are separate.
|
|
6
|
+
*/
|
|
7
|
+
import * as API from "@distilled.cloud/core/api";
|
|
8
|
+
import { getAnn } from "@distilled.cloud/core/protocol-http";
|
|
9
|
+
import * as Effect from "effect/Effect";
|
|
10
|
+
import * as Layer from "effect/Layer";
|
|
11
|
+
import * as Schema from "effect/Schema";
|
|
12
|
+
import { OpenBaoParseError } from "./errors.ts";
|
|
13
|
+
import { mountTableSymbol } from "./traits.ts";
|
|
14
|
+
|
|
15
|
+
const invalidTable = () =>
|
|
16
|
+
new OpenBaoParseError({
|
|
17
|
+
body: undefined,
|
|
18
|
+
cause: "Response does not match the declared OpenBao mount table schema",
|
|
19
|
+
});
|
|
20
|
+
const record = (body: unknown): body is Record<string, unknown> =>
|
|
21
|
+
typeof body === "object" && body !== null && !Array.isArray(body);
|
|
22
|
+
|
|
23
|
+
export const withMountTables = (
|
|
24
|
+
base: Layer.Layer<API.Protocol>,
|
|
25
|
+
): Layer.Layer<API.Protocol> =>
|
|
26
|
+
Layer.effect(
|
|
27
|
+
API.Protocol,
|
|
28
|
+
Effect.gen(function* () {
|
|
29
|
+
const protocol = yield* API.Protocol;
|
|
30
|
+
return API.Protocol.of({
|
|
31
|
+
encode: protocol.encode,
|
|
32
|
+
decode: (args) => {
|
|
33
|
+
if (
|
|
34
|
+
!getAnn(args.outputAst, mountTableSymbol) ||
|
|
35
|
+
args.response.status >= 400 ||
|
|
36
|
+
args.config.output === undefined
|
|
37
|
+
)
|
|
38
|
+
return protocol.decode(args);
|
|
39
|
+
// These schemas use wire names and contain no sensitive transforms.
|
|
40
|
+
// Validate the original envelope before core's empty-body fallback;
|
|
41
|
+
// retain unknown metadata after validation for forward compatibility.
|
|
42
|
+
// Neither body values nor schema diagnostics may enter parse errors.
|
|
43
|
+
const output = args.config.output;
|
|
44
|
+
return args.response.json.pipe(
|
|
45
|
+
Effect.mapError(invalidTable),
|
|
46
|
+
Effect.flatMap((envelope) =>
|
|
47
|
+
record(envelope) && record(envelope.data)
|
|
48
|
+
? Schema.decodeUnknownEffect(Schema.toType(output))(
|
|
49
|
+
envelope.data,
|
|
50
|
+
).pipe(
|
|
51
|
+
Effect.as(envelope.data),
|
|
52
|
+
Effect.mapError(invalidTable),
|
|
53
|
+
)
|
|
54
|
+
: Effect.fail(invalidTable()),
|
|
55
|
+
),
|
|
56
|
+
) as Effect.Effect<unknown>;
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
}),
|
|
60
|
+
).pipe(Layer.provide(base));
|
|
@@ -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.
|
|
@@ -51,6 +53,7 @@ import {
|
|
|
51
53
|
} from "@distilled.cloud/core/protocol-rest";
|
|
52
54
|
import { Credentials, type Config } from "./credentials.ts";
|
|
53
55
|
import { UnknownOpenBaoError, type DefaultErrors } from "./errors.ts";
|
|
56
|
+
import { withMountTables } from "./protocol-mount-tables.ts";
|
|
54
57
|
|
|
55
58
|
/**
|
|
56
59
|
* Error channel shared by every generated OpenBao operation. Generated
|
|
@@ -100,7 +103,10 @@ export const OpenBaoProtocol: Layer.Layer<API.Protocol> =
|
|
|
100
103
|
}),
|
|
101
104
|
baseUrl: (creds) => creds.apiBaseUrl,
|
|
102
105
|
headers: (creds) => ({
|
|
103
|
-
|
|
106
|
+
...(creds.token && Redacted.value(creds.token) !== ""
|
|
107
|
+
? { "X-Vault-Token": Redacted.value(creds.token) }
|
|
108
|
+
: {}),
|
|
109
|
+
"X-Vault-Request": "true",
|
|
104
110
|
...(creds.namespace ? { "X-Vault-Namespace": creds.namespace } : {}),
|
|
105
111
|
Accept: "application/json",
|
|
106
112
|
}),
|
|
@@ -117,4 +123,4 @@ export const OpenBaoProtocol: Layer.Layer<API.Protocol> =
|
|
|
117
123
|
message,
|
|
118
124
|
body,
|
|
119
125
|
}),
|
|
120
|
-
});
|
|
126
|
+
}).pipe(withMountTables);
|
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
|
package/src/services/auth.ts
CHANGED
|
@@ -83,9 +83,103 @@ export const AuthListEnabledMethodsRequest = /*@__PURE__*/ S.suspend(() =>
|
|
|
83
83
|
identifier: "AuthListEnabledMethodsRequest",
|
|
84
84
|
}) as any as S.Schema<AuthListEnabledMethodsRequest>;
|
|
85
85
|
|
|
86
|
-
export
|
|
86
|
+
export type MountOptions = { [key: string]: string | undefined };
|
|
87
|
+
export const MountOptions = /*@__PURE__*/ S.Record(
|
|
88
|
+
S.String,
|
|
89
|
+
S.String,
|
|
90
|
+
) as any as S.Schema<MountOptions>;
|
|
91
|
+
|
|
92
|
+
export type MountStrings = Array<string>;
|
|
93
|
+
export const MountStrings = /*@__PURE__*/ S.Array(
|
|
94
|
+
S.String,
|
|
95
|
+
) as any as S.Schema<MountStrings>;
|
|
96
|
+
|
|
97
|
+
export interface MountUserLockoutConfig {
|
|
98
|
+
user_lockout_counter_reset_duration: number;
|
|
99
|
+
user_lockout_threshold: number;
|
|
100
|
+
user_lockout_duration: number;
|
|
101
|
+
user_lockout_disable: boolean;
|
|
102
|
+
}
|
|
103
|
+
export const MountUserLockoutConfig = /*@__PURE__*/ S.suspend(() =>
|
|
104
|
+
S.Struct({
|
|
105
|
+
user_lockout_counter_reset_duration: S.Number,
|
|
106
|
+
user_lockout_threshold: S.Number,
|
|
107
|
+
user_lockout_duration: S.Number,
|
|
108
|
+
user_lockout_disable: S.Boolean,
|
|
109
|
+
}),
|
|
110
|
+
).annotate({
|
|
111
|
+
identifier: "MountUserLockoutConfig",
|
|
112
|
+
}) as any as S.Schema<MountUserLockoutConfig>;
|
|
113
|
+
|
|
114
|
+
export interface MountConfig {
|
|
115
|
+
default_lease_ttl: number;
|
|
116
|
+
max_lease_ttl: number;
|
|
117
|
+
force_no_cache: boolean;
|
|
118
|
+
audit_non_hmac_request_keys?: MountStrings;
|
|
119
|
+
audit_non_hmac_response_keys?: MountStrings;
|
|
120
|
+
passthrough_request_headers?: MountStrings;
|
|
121
|
+
allowed_response_headers?: MountStrings;
|
|
122
|
+
listing_visibility?: string;
|
|
123
|
+
token_type?: string;
|
|
124
|
+
user_lockout_config?: MountUserLockoutConfig;
|
|
125
|
+
}
|
|
126
|
+
export const MountConfig = /*@__PURE__*/ S.suspend(() =>
|
|
127
|
+
S.Struct({
|
|
128
|
+
default_lease_ttl: S.Number,
|
|
129
|
+
max_lease_ttl: S.Number,
|
|
130
|
+
force_no_cache: S.Boolean,
|
|
131
|
+
audit_non_hmac_request_keys: S.optional(MountStrings),
|
|
132
|
+
audit_non_hmac_response_keys: S.optional(MountStrings),
|
|
133
|
+
passthrough_request_headers: S.optional(MountStrings),
|
|
134
|
+
allowed_response_headers: S.optional(MountStrings),
|
|
135
|
+
listing_visibility: S.optional(S.String),
|
|
136
|
+
token_type: S.optional(S.String),
|
|
137
|
+
user_lockout_config: S.optional(MountUserLockoutConfig),
|
|
138
|
+
}),
|
|
139
|
+
).annotate({ identifier: "MountConfig" }) as any as S.Schema<MountConfig>;
|
|
140
|
+
|
|
141
|
+
export interface MountInfo {
|
|
142
|
+
type: string;
|
|
143
|
+
description: string;
|
|
144
|
+
accessor: string;
|
|
145
|
+
uuid: string;
|
|
146
|
+
plugin_version: string;
|
|
147
|
+
running_plugin_version: string;
|
|
148
|
+
running_sha256: string;
|
|
149
|
+
local: boolean;
|
|
150
|
+
seal_wrap: boolean;
|
|
151
|
+
external_entropy_access: boolean;
|
|
152
|
+
options: MountOptions | null;
|
|
153
|
+
config: MountConfig;
|
|
154
|
+
deprecation_status?: string;
|
|
155
|
+
}
|
|
156
|
+
export const MountInfo = /*@__PURE__*/ S.suspend(() =>
|
|
157
|
+
S.Struct({
|
|
158
|
+
type: S.String,
|
|
159
|
+
description: S.String,
|
|
160
|
+
accessor: S.String,
|
|
161
|
+
uuid: S.String,
|
|
162
|
+
plugin_version: S.String,
|
|
163
|
+
running_plugin_version: S.String,
|
|
164
|
+
running_sha256: S.String,
|
|
165
|
+
local: S.Boolean,
|
|
166
|
+
seal_wrap: S.Boolean,
|
|
167
|
+
external_entropy_access: S.Boolean,
|
|
168
|
+
options: S.NullOr(MountOptions),
|
|
169
|
+
config: MountConfig,
|
|
170
|
+
deprecation_status: S.optional(S.String),
|
|
171
|
+
}),
|
|
172
|
+
).annotate({ identifier: "MountInfo" }) as any as S.Schema<MountInfo>;
|
|
173
|
+
|
|
174
|
+
export type MountTable = { [key: string]: MountInfo | undefined };
|
|
175
|
+
export const MountTable = /*@__PURE__*/ S.Record(
|
|
176
|
+
S.String,
|
|
177
|
+
MountInfo,
|
|
178
|
+
) as any as S.Schema<MountTable>;
|
|
179
|
+
|
|
180
|
+
export type AuthListEnabledMethodsResponse = MountTable;
|
|
87
181
|
export const AuthListEnabledMethodsResponse = /*@__PURE__*/ S.suspend(() =>
|
|
88
|
-
|
|
182
|
+
MountTable.pipe(T.MountTable()),
|
|
89
183
|
).annotate({
|
|
90
184
|
identifier: "AuthListEnabledMethodsResponse",
|
|
91
185
|
}) as any as S.Schema<AuthListEnabledMethodsResponse>;
|
package/src/services/mounts.ts
CHANGED
|
@@ -83,9 +83,103 @@ export const MountsListSecretsEnginesRequest = /*@__PURE__*/ S.suspend(() =>
|
|
|
83
83
|
identifier: "MountsListSecretsEnginesRequest",
|
|
84
84
|
}) as any as S.Schema<MountsListSecretsEnginesRequest>;
|
|
85
85
|
|
|
86
|
-
export
|
|
86
|
+
export type MountOptions = { [key: string]: string | undefined };
|
|
87
|
+
export const MountOptions = /*@__PURE__*/ S.Record(
|
|
88
|
+
S.String,
|
|
89
|
+
S.String,
|
|
90
|
+
) as any as S.Schema<MountOptions>;
|
|
91
|
+
|
|
92
|
+
export type MountStrings = Array<string>;
|
|
93
|
+
export const MountStrings = /*@__PURE__*/ S.Array(
|
|
94
|
+
S.String,
|
|
95
|
+
) as any as S.Schema<MountStrings>;
|
|
96
|
+
|
|
97
|
+
export interface MountUserLockoutConfig {
|
|
98
|
+
user_lockout_counter_reset_duration: number;
|
|
99
|
+
user_lockout_threshold: number;
|
|
100
|
+
user_lockout_duration: number;
|
|
101
|
+
user_lockout_disable: boolean;
|
|
102
|
+
}
|
|
103
|
+
export const MountUserLockoutConfig = /*@__PURE__*/ S.suspend(() =>
|
|
104
|
+
S.Struct({
|
|
105
|
+
user_lockout_counter_reset_duration: S.Number,
|
|
106
|
+
user_lockout_threshold: S.Number,
|
|
107
|
+
user_lockout_duration: S.Number,
|
|
108
|
+
user_lockout_disable: S.Boolean,
|
|
109
|
+
}),
|
|
110
|
+
).annotate({
|
|
111
|
+
identifier: "MountUserLockoutConfig",
|
|
112
|
+
}) as any as S.Schema<MountUserLockoutConfig>;
|
|
113
|
+
|
|
114
|
+
export interface MountConfig {
|
|
115
|
+
default_lease_ttl: number;
|
|
116
|
+
max_lease_ttl: number;
|
|
117
|
+
force_no_cache: boolean;
|
|
118
|
+
audit_non_hmac_request_keys?: MountStrings;
|
|
119
|
+
audit_non_hmac_response_keys?: MountStrings;
|
|
120
|
+
passthrough_request_headers?: MountStrings;
|
|
121
|
+
allowed_response_headers?: MountStrings;
|
|
122
|
+
listing_visibility?: string;
|
|
123
|
+
token_type?: string;
|
|
124
|
+
user_lockout_config?: MountUserLockoutConfig;
|
|
125
|
+
}
|
|
126
|
+
export const MountConfig = /*@__PURE__*/ S.suspend(() =>
|
|
127
|
+
S.Struct({
|
|
128
|
+
default_lease_ttl: S.Number,
|
|
129
|
+
max_lease_ttl: S.Number,
|
|
130
|
+
force_no_cache: S.Boolean,
|
|
131
|
+
audit_non_hmac_request_keys: S.optional(MountStrings),
|
|
132
|
+
audit_non_hmac_response_keys: S.optional(MountStrings),
|
|
133
|
+
passthrough_request_headers: S.optional(MountStrings),
|
|
134
|
+
allowed_response_headers: S.optional(MountStrings),
|
|
135
|
+
listing_visibility: S.optional(S.String),
|
|
136
|
+
token_type: S.optional(S.String),
|
|
137
|
+
user_lockout_config: S.optional(MountUserLockoutConfig),
|
|
138
|
+
}),
|
|
139
|
+
).annotate({ identifier: "MountConfig" }) as any as S.Schema<MountConfig>;
|
|
140
|
+
|
|
141
|
+
export interface MountInfo {
|
|
142
|
+
type: string;
|
|
143
|
+
description: string;
|
|
144
|
+
accessor: string;
|
|
145
|
+
uuid: string;
|
|
146
|
+
plugin_version: string;
|
|
147
|
+
running_plugin_version: string;
|
|
148
|
+
running_sha256: string;
|
|
149
|
+
local: boolean;
|
|
150
|
+
seal_wrap: boolean;
|
|
151
|
+
external_entropy_access: boolean;
|
|
152
|
+
options: MountOptions | null;
|
|
153
|
+
config: MountConfig;
|
|
154
|
+
deprecation_status?: string;
|
|
155
|
+
}
|
|
156
|
+
export const MountInfo = /*@__PURE__*/ S.suspend(() =>
|
|
157
|
+
S.Struct({
|
|
158
|
+
type: S.String,
|
|
159
|
+
description: S.String,
|
|
160
|
+
accessor: S.String,
|
|
161
|
+
uuid: S.String,
|
|
162
|
+
plugin_version: S.String,
|
|
163
|
+
running_plugin_version: S.String,
|
|
164
|
+
running_sha256: S.String,
|
|
165
|
+
local: S.Boolean,
|
|
166
|
+
seal_wrap: S.Boolean,
|
|
167
|
+
external_entropy_access: S.Boolean,
|
|
168
|
+
options: S.NullOr(MountOptions),
|
|
169
|
+
config: MountConfig,
|
|
170
|
+
deprecation_status: S.optional(S.String),
|
|
171
|
+
}),
|
|
172
|
+
).annotate({ identifier: "MountInfo" }) as any as S.Schema<MountInfo>;
|
|
173
|
+
|
|
174
|
+
export type MountTable = { [key: string]: MountInfo | undefined };
|
|
175
|
+
export const MountTable = /*@__PURE__*/ S.Record(
|
|
176
|
+
S.String,
|
|
177
|
+
MountInfo,
|
|
178
|
+
) as any as S.Schema<MountTable>;
|
|
179
|
+
|
|
180
|
+
export type MountsListSecretsEnginesResponse = MountTable;
|
|
87
181
|
export const MountsListSecretsEnginesResponse = /*@__PURE__*/ S.suspend(() =>
|
|
88
|
-
|
|
182
|
+
MountTable.pipe(T.MountTable()),
|
|
89
183
|
).annotate({
|
|
90
184
|
identifier: "MountsListSecretsEnginesResponse",
|
|
91
185
|
}) as any as S.Schema<MountsListSecretsEnginesResponse>;
|
package/src/traits.ts
CHANGED
|
@@ -4,8 +4,16 @@
|
|
|
4
4
|
* Re-exports the generic protocol traits from core so generated operations
|
|
5
5
|
* import everything from one place. OpenBao speaks plain token-REST JSON
|
|
6
6
|
* with a `data`-enveloped success body (unwrapped in `protocol.ts`), so
|
|
7
|
-
*
|
|
7
|
+
* MountTable marks the two inventory responses whose data is a path-keyed map.
|
|
8
8
|
*/
|
|
9
|
+
import { makeAnnotation } from "@distilled.cloud/core/trait";
|
|
10
|
+
|
|
11
|
+
export const mountTableSymbol = Symbol.for(
|
|
12
|
+
"@distilled.cloud/openbao/mount-table",
|
|
13
|
+
);
|
|
14
|
+
/** A typed dynamic map inside a required logical-response data envelope. */
|
|
15
|
+
export const MountTable = () => makeAnnotation(mountTableSymbol, true);
|
|
16
|
+
|
|
9
17
|
export {
|
|
10
18
|
Body,
|
|
11
19
|
Header,
|