import {
AuthAdministrativeScopes,
AuthSessionId,
AuthStandardClientScopes,
} from "@t3tools/contracts";
import * as Console from "effect/Console";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as References from "effect/References";
import { Argument, Command, Flag, GlobalFlag } from "effect/unstable/cli";
import * as EnvironmentAuth from "../auth/EnvironmentAuth.ts";
import {
formatIssuedPairingCredential,
formatIssuedSession,
formatPairingCredentialList,
formatSessionList,
} from "../cliAuthFormat.ts";
import * as ServerConfig from "../config.ts";
import {
authLocationFlags,
type CliAuthLocationFlags,
DurationFromString,
resolveCliAuthConfig,
} from "./config.ts";
const runWithEnvironmentAuth = (
flags: CliAuthLocationFlags,
run: (environmentAuth: EnvironmentAuth.EnvironmentAuth["Service"]) => Effect.Effect,
options?: {
readonly quietLogs?: boolean;
},
) =>
Effect.gen(function* () {
const logLevel = yield* GlobalFlag.LogLevel;
const config = yield* resolveCliAuthConfig(flags, logLevel);
const minimumLogLevel = options?.quietLogs ? "Error" : config.logLevel;
return yield* Effect.gen(function* () {
const environmentAuth = yield* EnvironmentAuth.EnvironmentAuth;
return yield* run(environmentAuth);
}).pipe(
Effect.provide(
Layer.mergeAll(EnvironmentAuth.runtimeLayer).pipe(
Layer.provide(ServerConfig.layer(config)),
Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)),
),
),
);
});
const ttlFlag = Flag.string("ttl").pipe(
Flag.withSchema(DurationFromString),
Flag.withDescription("TTL, for example `5m`, `1h`, `30d`, or `15 minutes`."),
Flag.optional,
);
const jsonFlag = Flag.boolean("json").pipe(
Flag.withDescription("Emit JSON instead of human-readable output."),
Flag.withDefault(false),
);
const labelFlag = Flag.string("label").pipe(
Flag.withDescription("Optional human-readable label."),
Flag.optional,
);
const subjectFlag = Flag.string("subject").pipe(
Flag.withDescription("Optional session subject."),
Flag.optional,
);
const baseUrlFlag = Flag.string("base-url").pipe(
Flag.withDescription("Optional public base URL used to print a ready `/pair#token=...` link."),
Flag.optional,
);
const tokenOnlyFlag = Flag.boolean("token-only").pipe(
Flag.withDescription("Print only the issued bearer token."),
Flag.withDefault(false),
);
const pairingCreateCommand = Command.make("create", {
...authLocationFlags,
ttl: ttlFlag,
label: labelFlag,
baseUrl: baseUrlFlag,
json: jsonFlag,
}).pipe(
Command.withDescription("Issue a new client pairing token."),
Command.withHandler((flags) =>
runWithEnvironmentAuth(
flags,
(environmentAuth) =>
Effect.gen(function* () {
const issued = yield* environmentAuth.createPairingLink({
scopes: AuthStandardClientScopes,
subject: "one-time-token",
...(Option.isSome(flags.ttl) ? { ttl: flags.ttl.value } : {}),
...(Option.isSome(flags.label) ? { label: flags.label.value } : {}),
});
const output = formatIssuedPairingCredential(issued, {
json: flags.json,
...(Option.isSome(flags.baseUrl) ? { baseUrl: flags.baseUrl.value } : {}),
});
yield* Console.log(output);
}),
{
quietLogs: flags.json,
},
),
),
);
const pairingListCommand = Command.make("list", {
...authLocationFlags,
json: jsonFlag,
}).pipe(
Command.withDescription("List active client pairing tokens without revealing their secrets."),
Command.withHandler((flags) =>
runWithEnvironmentAuth(
flags,
(environmentAuth) =>
Effect.gen(function* () {
const pairingLinks = yield* environmentAuth.listPairingLinks({
excludeSubjects: [EnvironmentAuth.INTERNAL_ADMINISTRATIVE_BOOTSTRAP_SUBJECT],
});
yield* Console.log(formatPairingCredentialList(pairingLinks, { json: flags.json }));
}),
{
quietLogs: flags.json,
},
),
),
);
const pairingRevokeCommand = Command.make("revoke", {
...authLocationFlags,
id: Argument.string("id").pipe(Argument.withDescription("Pairing credential id to revoke.")),
}).pipe(
Command.withDescription("Revoke an active client pairing token."),
Command.withHandler((flags) =>
runWithEnvironmentAuth(flags, (environmentAuth) =>
Effect.gen(function* () {
const revoked = yield* environmentAuth.revokePairingLink(flags.id);
yield* Console.log(
revoked
? `Revoked pairing credential ${flags.id}.\n`
: `No active pairing credential found for ${flags.id}.\n`,
);
}),
),
),
);
const pairingCommand = Command.make("pairing").pipe(
Command.withDescription("Manage one-time client pairing tokens."),
Command.withSubcommands([pairingCreateCommand, pairingListCommand, pairingRevokeCommand]),
);
const sessionIssueCommand = Command.make("issue", {
...authLocationFlags,
ttl: ttlFlag,
label: labelFlag,
subject: subjectFlag,
tokenOnly: tokenOnlyFlag,
json: jsonFlag,
}).pipe(
Command.withDescription("Issue a scoped bearer access token for headless or remote clients."),
Command.withHandler((flags) =>
runWithEnvironmentAuth(
flags,
(environmentAuth) =>
Effect.gen(function* () {
const issued = yield* environmentAuth.issueSession({
scopes: AuthAdministrativeScopes,
...(Option.isSome(flags.ttl) ? { ttl: flags.ttl.value } : {}),
...(Option.isSome(flags.label) ? { label: flags.label.value } : {}),
...(Option.isSome(flags.subject) ? { subject: flags.subject.value } : {}),
});
yield* Console.log(
formatIssuedSession(issued, {
json: flags.json,
tokenOnly: flags.tokenOnly,
}),
);
}),
{
quietLogs: flags.json || flags.tokenOnly,
},
),
),
);
const sessionListCommand = Command.make("list", {
...authLocationFlags,
json: jsonFlag,
}).pipe(
Command.withDescription("List active sessions without revealing bearer tokens."),
Command.withHandler((flags) =>
runWithEnvironmentAuth(
flags,
(environmentAuth) =>
Effect.gen(function* () {
const sessions = yield* environmentAuth.listSessions();
yield* Console.log(formatSessionList(sessions, { json: flags.json }));
}),
{
quietLogs: flags.json,
},
),
),
);
const sessionRevokeCommand = Command.make("revoke", {
...authLocationFlags,
sessionId: Argument.string("session-id").pipe(
Argument.withDescription("Session id to revoke."),
Argument.withSchema(AuthSessionId),
),
}).pipe(
Command.withDescription("Revoke an active session."),
Command.withHandler((flags) =>
runWithEnvironmentAuth(flags, (environmentAuth) =>
Effect.gen(function* () {
const revoked = yield* environmentAuth.revokeSession(flags.sessionId);
yield* Console.log(
revoked
? `Revoked session ${flags.sessionId}.\n`
: `No active session found for ${flags.sessionId}.\n`,
);
}),
),
),
);
const sessionCommand = Command.make("session").pipe(
Command.withDescription("Manage bearer sessions."),
Command.withSubcommands([sessionIssueCommand, sessionListCommand, sessionRevokeCommand]),
);
export const authCommand = Command.make("auth").pipe(
Command.withDescription("Manage the local auth control plane for headless deployments."),
Command.withSubcommands([pairingCommand, sessionCommand]),
);