import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi"; import { Schema } from "effect"; import { InternalError } from "@executor-js/sdk/shared"; import { OnePasswordError } from "../sdk/errors"; import { OnePasswordAccountUpsert } from "../sdk/plugin"; import { RedactedOnePasswordConfig, Vault, ConnectionStatus } from "../sdk/types"; // --------------------------------------------------------------------------- // Payloads // // v2: config is a single per-owner binding the extension derives from the // executor's owner binding — there are no scope segments in the path. The // configure payload carries one account upsert (including the // service-account token); reads return the redacted projection so the token // never leaves the plugin. // --------------------------------------------------------------------------- const ConfigurePayload = OnePasswordAccountUpsert; const ConfigureResponse = Schema.Struct({ accountId: Schema.String, }); const RemoveConfigParams = Schema.Struct({ accountId: Schema.optional(Schema.String), }); const ListVaultsParams = Schema.Struct({ authKind: Schema.Literals(["desktop-app", "service-account"]), account: Schema.String, }); // --------------------------------------------------------------------------- // Responses // --------------------------------------------------------------------------- const ListVaultsResponse = Schema.Struct({ vaults: Schema.Array(Vault), }); const GetConfigResponse = Schema.NullOr(RedactedOnePasswordConfig); // --------------------------------------------------------------------------- // Group // // Plugin SDK errors (OnePasswordError) are declared once per endpoint via the // `error` field — the error carries its own 502 status via `HttpApiSchema` // annotations in errors.ts. // // `InternalError` is the shared opaque 500 schema translated at the HTTP edge // by `withCapture`. Storage failures on `ctx.storage` flow through as // `StorageFailure` in the typed channel and are captured + downgraded to // `InternalError({ traceId })` at Layer composition. // --------------------------------------------------------------------------- export const OnePasswordGroup = HttpApiGroup.make("onepassword") .add( HttpApiEndpoint.get("getConfig", "/onepassword/config", { success: GetConfigResponse, error: [InternalError, OnePasswordError], }), ) .add( HttpApiEndpoint.put("configure", "/onepassword/config", { payload: ConfigurePayload, success: ConfigureResponse, error: [InternalError, OnePasswordError], }), ) .add( HttpApiEndpoint.delete("removeConfig", "/onepassword/config", { query: RemoveConfigParams, success: Schema.Void, error: [InternalError, OnePasswordError], }), ) .add( HttpApiEndpoint.get("status", "/onepassword/status", { success: ConnectionStatus, error: [InternalError, OnePasswordError], }), ) .add( HttpApiEndpoint.get("listVaults", "/onepassword/vaults", { query: ListVaultsParams, success: ListVaultsResponse, error: [InternalError, OnePasswordError], }), );