1import * as GCP from "@/GCP";
2import * as Effect from "effect/Effect";
3import * as Result from "effect/Result";
4import { serveProbes } from "../../bindingHost.ts";
5
6/** Secret the per-operation AddSecretVersion / AccessSecretVersion bind. */
7export const OpsSecret = GCP.SecretManager.Secret("OpsSecret", {});
8
9/** Regional secret the per-operation bindings bind. */
10export const RegionalSecret = GCP.SecretManager.LocationsSecret(
11 "RegionalSecret",
12 { location: "us-central1" },
13);
14
15/** Secret only {@link GCP.SecretManager.ReadSecret} binds (seeded by the test). */
16export const ReadOnlySecret = GCP.SecretManager.Secret("ReadOnlySecret", {});
17
18/** Secret only {@link GCP.SecretManager.WriteSecret} binds. */
19export const WriteOnlySecret = GCP.SecretManager.Secret("WriteOnlySecret", {});
20
21/** Secret only {@link GCP.SecretManager.ReadWriteSecret} binds. */
22export const ReadWriteOnlySecret = GCP.SecretManager.Secret(
23 "ReadWriteOnlySecret",
24 {},
25);
26
27/** Payload the test seeds into {@link ReadOnlySecret}. */
28export const SEEDED = "seeded-value";
29
30/**
31 * Effect-native Cloud Run service exercising every Secret Manager binding as
32 * its own runtime service account. Deployed from {@link ../Bindings.test.ts}.
33 */
34export default class SecretManagerBindingsHost extends GCP.Function<SecretManagerBindingsHost>()(
35 "SecretManagerBindingsHost",
36 { main: import.meta.url, invokerIamDisabled: true },
37 Effect.gen(function* () {
38 const addVersion = yield* GCP.SecretManager.AddSecretVersion(OpsSecret);
39 const access = yield* GCP.SecretManager.AccessSecretVersion(OpsSecret);
40 const addRegional =
41 yield* GCP.SecretManager.AddSecretVersion(RegionalSecret);
42 const accessRegional =
43 yield* GCP.SecretManager.AccessSecretVersion(RegionalSecret);
44 const reader = yield* GCP.SecretManager.ReadSecret(ReadOnlySecret);
45 const writer = yield* GCP.SecretManager.WriteSecret(WriteOnlySecret);
46 const both = yield* GCP.SecretManager.ReadWriteSecret(ReadWriteOnlySecret);
47
48 const roundTrip = (
49 add: typeof addVersion,
50 read: typeof access,
51 value: string,
52 ) =>
53 Effect.gen(function* () {
54 const payload = btoa(value);
55 const version = yield* add({ payload: { data: payload } });
56 const accessed = yield* read({
57 version: version.name?.split("/").pop(),
58 });
59 return {
60 version: version.name,
61 accessedName: accessed.name,
62 data: accessed.payload?.data,
63 payload,
64 };
65 });
66
67 return {
68 fetch: serveProbes({
69 ops: roundTrip(addVersion, access, "per-op-global"),
70 opsRegional: roundTrip(addRegional, accessRegional, "per-op-regional"),
71 read: Effect.gen(function* () {
72 const latest = yield* reader.access();
73 const bytes = yield* reader.accessBytes("latest");
74 const missing = yield* reader.access("999");
75 return {
76 latest,
77 bytes: bytes && new TextDecoder().decode(bytes),
78 missing: missing === undefined,
79 };
80 }),
81 write: Effect.gen(function* () {
82 const v1 = yield* writer.addVersion("one");
83 const v2 = yield* writer.addVersion(new TextEncoder().encode("two"));
84 yield* writer.disableVersion(v2);
85 yield* writer.destroyVersion(v1.split("/").pop() ?? v1);
86 yield* writer.destroyVersion("999");
87 return { v1, v2 };
88 }),
89 readWrite: Effect.gen(function* () {
90 const v1 = yield* both.addVersion("one");
91 const v2 = yield* both.addVersion(new TextEncoder().encode("two"));
92 const latest = yield* both.access();
93 const first = yield* both.accessBytes(v1);
94 yield* both.disableVersion(v2);
95 const disabled = yield* Effect.result(both.access(v2));
96 yield* both.destroyVersion(v1);
97 const destroyed = yield* both.access(v1);
98 return {
99 v1,
100 v2,
101 latest,
102 first: first && new TextDecoder().decode(first),
103 disabledReadsUndefined:
104 Result.isSuccess(disabled) && disabled.success === undefined,
105 destroyedReadsUndefined: destroyed === undefined,
106 };
107 }),
108 }),
109 };
110 }).pipe(
111 Effect.provide(GCP.SecretManager.AddSecretVersionHttp),
112 Effect.provide(GCP.SecretManager.AccessSecretVersionHttp),
113 Effect.provide(GCP.SecretManager.ReadSecretHttp),
114 Effect.provide(GCP.SecretManager.WriteSecretHttp),
115 Effect.provide(GCP.SecretManager.ReadWriteSecretHttp),
116 ),
117) {}