@rikalabs/akter-cli 0.1.0-alpha.4 → 0.1.0-alpha.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0-alpha.6 (2026-10-11)
4
+
5
+ The CLI and framework release together on the `alpha` and `latest` npm dist-tags. CLI credential storage is unchanged; the matching framework adds `0034_cold_tier`, `0035_hot_table_foreign_keys` and opt-in cold objects. Rolling-upgrade safety from alpha.5 is **not established**; see the [framework changelog](https://github.com/Rika-Labs/akter/blob/main/packages/akter/CHANGELOG.md) and [alpha upgrade notes](https://docs.akter.dev/operations/alpha-upgrades) before upgrading runners.
6
+
7
+ - Adds the environment application-key contract to `@rikalabs/akter-cli/cloud-api`: `EnvironmentApiKeysGroup`, `EnvironmentApiKeyTenant`, `EnvironmentApiKey`, `CreateEnvironmentApiKey` and `CreatedEnvironmentApiKey`, composed into `CloudApi`. The additive routes create, list and revoke keys under `/api/projects/:projectId/environments/:environment/api-keys`; only creation returns `{ key, secret }`, while list returns metadata including revoked keys and revoke returns 204. These keys authenticate the deployed application, not the control plane; see the [environment API keys contract](https://docs.akter.dev/api/09-environment-api-keys).
8
+ - Adds `akter keys create <name> [--tenant <tenant>]`, `akter keys list` and `akter keys revoke <keyId>`, using stored control-plane credentials, `--project` (default `AKTER_PROJECT`) and `--env` (default `production`). An omitted tenant selects `default`; supplied tenants are validated. Create writes only the one-time secret to stdout and a save-now warning to stderr. List prints tab-separated metadata, never secrets; revoke confirms only server success. Metadata output strips terminal escapes and replaces control, line-separator and bidirectional characters without changing requests. Protect redirected secret output and keep it out of shared logs; see [CLI usage](https://docs.akter.dev/api/06-cli#akter-keys).
9
+ - Clarifies the cloud database report's four-session runner budget and rollout overlap; its wire schema is unchanged. Environment-key contract and CLI tests establish public client encoding, decoding and output, not cloud database authorization or edge authentication. Logs-follow interruption tests now wait for an actual outstanding HTTP poll before checking cancellation; production follow behavior is unchanged.
10
+
11
+ ## 0.1.0-alpha.5 (2026-10-09)
12
+
13
+ - Releases with the matching alpha.5 framework, which adds the supported four-session `Database.postgres({ url, preset: "low-connection" })` preset. CLI behavior and the bundled `@rikalabs/akter-cli/cloud-api` contract are unchanged from alpha.4.
14
+
3
15
  ## 0.1.0-alpha.4 (2026-10-09)
4
16
 
5
17
  - **Breaking cloud contract:** every environment uses customer Postgres through `DATABASE_URL`. `Environment.database`, when reported, is `{ source: "customer", state: "missing" | "reachable" | "unreachable", latency, latencyWarning, runnerCap }`. Latency is nullable p50 milliseconds; runner cap is a nullable integer. The managed source and provisioning, ready, read-only and failed states are removed.
@@ -629,7 +629,35 @@ declare const CloudApi_base: HttpApi.HttpApi<"akter-cloud", import("effect/http-
629
629
  readonly value: import("effect/Schema").String;
630
630
  }>>;
631
631
  readonly createdAt: import("effect/Schema").DateTimeUtc;
632
- }>>, import("effect/Schema").toCodecJson<typeof import("./errors.ts").Forbidden | typeof import("./errors.ts").NotFound | typeof import("./errors.ts").Conflict | typeof import("./errors.ts").NotImplemented | typeof import("./errors.ts").Unavailable>, Authentication, never>, false> | import("effect/http-api/HttpApiGroup").HttpApiGroup<"environmentVariables", import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"delete", "DELETE", "/api/projects/:projectId/environments/:environment/variables/:name", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
632
+ }>>, import("effect/Schema").toCodecJson<typeof import("./errors.ts").Forbidden | typeof import("./errors.ts").NotFound | typeof import("./errors.ts").Conflict | typeof import("./errors.ts").NotImplemented | typeof import("./errors.ts").Unavailable>, Authentication, never>, false> | import("effect/http-api/HttpApiGroup").HttpApiGroup<"environmentApiKeys", import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"create", "POST", "/api/projects/:projectId/environments/:environment/api-keys", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
633
+ projectId: import("effect/Schema").brand<import("effect/Schema").String, "ProjectId">;
634
+ environment: import("effect/Schema").Literals<readonly ["production", "staging", "dev"]>;
635
+ }>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
636
+ readonly name: import("effect/Schema").brand<import("effect/Schema").String, "Name">;
637
+ readonly tenant: import("effect/Schema").optional<import("effect/Schema").String>;
638
+ }>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
639
+ readonly key: import("effect/Schema").Struct<{
640
+ readonly id: import("effect/Schema").String;
641
+ readonly name: import("effect/Schema").String;
642
+ readonly tenant: import("effect/Schema").String;
643
+ readonly createdAt: import("effect/Schema").DateTimeUtc;
644
+ readonly revokedAt: import("effect/Schema").NullOr<import("effect/Schema").DateTimeUtc>;
645
+ }>;
646
+ readonly secret: import("effect/Schema").String;
647
+ }>>, import("effect/Schema").toCodecJson<typeof import("./errors.ts").Forbidden | typeof import("./errors.ts").NotFound | typeof import("./errors.ts").Conflict | typeof import("./errors.ts").NotImplemented | typeof import("./errors.ts").Unavailable>, Authentication, never> | import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"list", "GET", "/api/projects/:projectId/environments/:environment/api-keys", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
648
+ projectId: import("effect/Schema").brand<import("effect/Schema").String, "ProjectId">;
649
+ environment: import("effect/Schema").Literals<readonly ["production", "staging", "dev"]>;
650
+ }>>, never, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").$Array<import("effect/Schema").Struct<{
651
+ readonly id: import("effect/Schema").String;
652
+ readonly name: import("effect/Schema").String;
653
+ readonly tenant: import("effect/Schema").String;
654
+ readonly createdAt: import("effect/Schema").DateTimeUtc;
655
+ readonly revokedAt: import("effect/Schema").NullOr<import("effect/Schema").DateTimeUtc>;
656
+ }>>>, import("effect/Schema").toCodecJson<typeof import("./errors.ts").Forbidden | typeof import("./errors.ts").NotFound | typeof import("./errors.ts").NotImplemented | typeof import("./errors.ts").Unavailable>, Authentication, never> | import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"revoke", "DELETE", "/api/projects/:projectId/environments/:environment/api-keys/:keyId", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
657
+ projectId: import("effect/Schema").brand<import("effect/Schema").String, "ProjectId">;
658
+ environment: import("effect/Schema").Literals<readonly ["production", "staging", "dev"]>;
659
+ keyId: import("effect/Schema").String;
660
+ }>>, never, never, never, import("effect/Schema").toCodecJson<import("effect/http-api/HttpApiSchema").NoContent>, import("effect/Schema").toCodecJson<typeof import("./errors.ts").Forbidden | typeof import("./errors.ts").NotFound | typeof import("./errors.ts").Conflict | typeof import("./errors.ts").NotImplemented | typeof import("./errors.ts").Unavailable>, Authentication, never>, false> | import("effect/http-api/HttpApiGroup").HttpApiGroup<"environmentVariables", import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"delete", "DELETE", "/api/projects/:projectId/environments/:environment/variables/:name", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
633
661
  projectId: import("effect/Schema").brand<import("effect/Schema").String, "ProjectId">;
634
662
  environment: import("effect/Schema").Literals<readonly ["production", "staging", "dev"]>;
635
663
  name: import("effect/Schema").String;
@@ -105,6 +105,37 @@ declare const ProjectsGroup_base: HttpApiGroup.HttpApiGroup<"projects", HttpApiE
105
105
  }>>, Schema.toCodecJson<typeof import("../errors.ts").Forbidden | typeof import("../errors.ts").NotFound | typeof import("../errors.ts").Conflict | typeof import("../errors.ts").NotImplemented | typeof import("../errors.ts").Unavailable>, never, never>, false>;
106
106
  export declare class ProjectsGroup extends ProjectsGroup_base {
107
107
  }
108
+ declare const EnvironmentApiKeysGroup_base: HttpApiGroup.HttpApiGroup<"environmentApiKeys", HttpApiEndpoint.HttpApiEndpoint<"create", "POST", "/projects/:projectId/environments/:environment/api-keys", Schema.toCodecStringTree<Schema.Struct<{
109
+ projectId: Schema.brand<Schema.String, "ProjectId">;
110
+ environment: Schema.Literals<readonly ["production", "staging", "dev"]>;
111
+ }>>, never, Schema.toCodecJson<Schema.Struct<{
112
+ readonly name: Schema.brand<Schema.String, "Name">;
113
+ readonly tenant: Schema.optional<Schema.String>;
114
+ }>>, never, Schema.toCodecJson<Schema.Struct<{
115
+ readonly key: Schema.Struct<{
116
+ readonly id: Schema.String;
117
+ readonly name: Schema.String;
118
+ readonly tenant: Schema.String;
119
+ readonly createdAt: Schema.DateTimeUtc;
120
+ readonly revokedAt: Schema.NullOr<Schema.DateTimeUtc>;
121
+ }>;
122
+ readonly secret: Schema.String;
123
+ }>>, Schema.toCodecJson<typeof import("../errors.ts").Forbidden | typeof import("../errors.ts").NotFound | typeof import("../errors.ts").Conflict | typeof import("../errors.ts").NotImplemented | typeof import("../errors.ts").Unavailable>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"list", "GET", "/projects/:projectId/environments/:environment/api-keys", Schema.toCodecStringTree<Schema.Struct<{
124
+ projectId: Schema.brand<Schema.String, "ProjectId">;
125
+ environment: Schema.Literals<readonly ["production", "staging", "dev"]>;
126
+ }>>, never, never, never, Schema.toCodecJson<Schema.$Array<Schema.Struct<{
127
+ readonly id: Schema.String;
128
+ readonly name: Schema.String;
129
+ readonly tenant: Schema.String;
130
+ readonly createdAt: Schema.DateTimeUtc;
131
+ readonly revokedAt: Schema.NullOr<Schema.DateTimeUtc>;
132
+ }>>>, Schema.toCodecJson<typeof import("../errors.ts").Forbidden | typeof import("../errors.ts").NotFound | typeof import("../errors.ts").NotImplemented | typeof import("../errors.ts").Unavailable>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"revoke", "DELETE", "/projects/:projectId/environments/:environment/api-keys/:keyId", Schema.toCodecStringTree<Schema.Struct<{
133
+ projectId: Schema.brand<Schema.String, "ProjectId">;
134
+ environment: Schema.Literals<readonly ["production", "staging", "dev"]>;
135
+ keyId: Schema.String;
136
+ }>>, never, never, never, Schema.toCodecJson<import("effect/http-api/HttpApiSchema").NoContent>, Schema.toCodecJson<typeof import("../errors.ts").Forbidden | typeof import("../errors.ts").NotFound | typeof import("../errors.ts").Conflict | typeof import("../errors.ts").NotImplemented | typeof import("../errors.ts").Unavailable>, never, never>, false>;
137
+ export declare class EnvironmentApiKeysGroup extends EnvironmentApiKeysGroup_base {
138
+ }
108
139
  declare const EnvironmentVariablesGroup_base: HttpApiGroup.HttpApiGroup<"environmentVariables", HttpApiEndpoint.HttpApiEndpoint<"delete", "DELETE", "/projects/:projectId/environments/:environment/variables/:name", Schema.toCodecStringTree<Schema.Struct<{
109
140
  projectId: Schema.brand<Schema.String, "ProjectId">;
110
141
  environment: Schema.Literals<readonly ["production", "staging", "dev"]>;
@@ -2,14 +2,14 @@ export { Conflict, Forbidden, NotFound, NotFoundResource, NotImplemented, Payloa
2
2
  export { ApiKeyIdentity, Authentication, CurrentIdentity, Identity, SessionIdentity, apiKeyHeaderName, secureSessionCookieName, sessionCookieName, } from "./auth.ts";
3
3
  export { ActorAddress, ActorReference, ApiKeyId, BillingPeriod, CalendarDay, CommitSha, DeadLetterId, DeploymentId, DomainId, Email, EnvironmentName, InvitationId, InviteRole, EnvironmentId, InvoiceId, MemberId, Name, NonNegative, NonNegativeInt, OrganizationId, Page, ProjectId, RegionId, Role, SeriesPoint, Slug, Timestamp, UserId, pageQuery, } from "./primitives.ts";
4
4
  export { ApiKey, ApiKeyPermission, CreateApiKey, CreateInvitation, CreateOrganization, CreatedApiKey, DeleteAccount, Invitation, InvitationPreview, KnownPlan, InvitationStatus, Me, Member, MemberUser, NotificationEvent, NotificationPreference, NotificationSettings, Organization, OrganizationDeletion, OrganizationMembership, OrganizationPlan, PinActor, PersonalDataExport, PinnedActor, PlanId, Preferences, SetActiveOrganization, Theme, UpdateMemberRole, UpdateOrganization, UpdatePreferences, UnboundPlan, UnknownPlan, UpdateProfile, User, } from "./identity.ts";
5
- export { AddDomain, AddRegion, ConnectIntegration, CreateEnvironment, CreateProject, DnsRecord, Domain, DomainStatus, EnvVariable, EnvVariableName, Environment, Hostname, ImportEnvVariables, ImportEnvVariablesResult, Integration, IntegrationConnection, IntegrationKind, OwnedTable, Project, ProjectEndpoints, ProjectRegion, ProjectStatus, Region, SetEnvVariable, SetHomeRegion, UpdateProject, } from "./projects.ts";
5
+ export { AddDomain, AddRegion, ConnectIntegration, CreateEnvironment, CreateEnvironmentApiKey, CreatedEnvironmentApiKey, CreateProject, DnsRecord, Domain, DomainStatus, EnvVariable, EnvVariableName, Environment, EnvironmentApiKey, EnvironmentApiKeyTenant, Hostname, ImportEnvVariables, ImportEnvVariablesResult, Integration, IntegrationConnection, IntegrationKind, OwnedTable, Project, ProjectEndpoints, ProjectRegion, ProjectStatus, Region, SetEnvVariable, SetHomeRegion, UpdateProject, } from "./projects.ts";
6
6
  export { BuildLog, BuildLogLine, CreateDeployment, DeploymentAuthor, DeploymentDetail, DeploymentRunner, DeploymentSource, DeploymentStatus, DeploymentSummary, ImageDigest, MAX_SOURCE_BYTES, RecordBuild, FailBuild, RolloutStep, RolloutStepName, SOURCE_ENTRY, SourceArchive, SourceDigest, } from "./deployments.ts";
7
7
  export { ActorEvent, ActorInspector, ActorInstance, ActorJob, ActorTimelineEntry, ActorTypeActivity, ActorTypeSummary, CommandCaller, CommandFailed, CommandRefused, CommandExpired, RunnerDefect, CommandStreamGap, CommandLogEntry, QuotaErrors, QuotaExceeded, QuotaUnbound, CommandOutcome, CommandSent, CommandVolume, ConnectionsSummary, DeadLetter, JobStatus, JobTypeStats, JobsSummary, LatencyBucket, Overview, OwnedTableRows, Receipt, Schedule, SearchResult, SendCommand, SeriesWindow, SidebarCounts, TimersSummary, TurnLatency, Workflow, } from "./runtime.ts";
8
8
  export { AuditEntry, BillingSummary, CapState, CardPaymentMethod, CatalogPlan, ComputeSize, ComputeUsage, PlanCatalog, PlanFeature, HostedSession, Invoice, LinkPaymentMethod, PaymentMethod, Plan, SetSpendLimit, SpendLimit, StartCheckout, PlanChange, Usage, UsageMeter, UsageMeterName, UsagePricing, } from "./billing.ts";
9
9
  export { CloudApi } from "./contract.ts";
10
10
  export { LogCursor, LogLimit, LogWait, MAX_LOG_LINES, MAX_LOG_TEXT_BYTES, MAX_LOG_WAIT_SECONDS, MAX_LOG_WINDOW_SECONDS, RunnerLogLine, RunnerLogPage, logQuery, } from "./logs.ts";
11
11
  export { AccountGroup, ApiKeysGroup, InvitationsGroup, MembersGroup, OrganizationsGroup, } from "./groups/account.ts";
12
- export { DomainsGroup, EnvironmentVariablesGroup, IntegrationsGroup, ProjectsGroup, RegionsGroup, } from "./groups/projects.ts";
12
+ export { DomainsGroup, EnvironmentApiKeysGroup, EnvironmentVariablesGroup, IntegrationsGroup, ProjectsGroup, RegionsGroup, } from "./groups/projects.ts";
13
13
  export { DeploymentsGroup } from "./groups/deployments.ts";
14
14
  export { AuditGroup, BillingGroup, UsageGroup } from "./groups/billing.ts";
15
15
  export { RuntimeGroup } from "./groups/runtime.ts";
@@ -318,6 +318,22 @@ var Environment = Schema5.Struct({
318
318
  }))
319
319
  });
320
320
  var CreateEnvironment = Schema5.Struct({ name: EnvironmentName });
321
+ var EnvironmentApiKeyTenant = Schema5.String.check(Schema5.isPattern(/^[A-Za-z0-9._:-]{1,128}$/u));
322
+ var EnvironmentApiKey = Schema5.Struct({
323
+ id: Schema5.String,
324
+ name: Schema5.String,
325
+ tenant: Schema5.String,
326
+ createdAt: Timestamp,
327
+ revokedAt: Schema5.NullOr(Timestamp)
328
+ });
329
+ var CreateEnvironmentApiKey = Schema5.Struct({
330
+ name: Name,
331
+ tenant: Schema5.optional(EnvironmentApiKeyTenant)
332
+ });
333
+ var CreatedEnvironmentApiKey = Schema5.Struct({
334
+ key: EnvironmentApiKey,
335
+ secret: Schema5.String
336
+ });
321
337
  var EnvVariable = Schema5.Struct({
322
338
  name: Schema5.String,
323
339
  usedBy: Schema5.Array(Schema5.String),
@@ -1233,6 +1249,21 @@ class ProjectsGroup extends HttpApiGroup4.make("projects").add(HttpApiEndpoint4.
1233
1249
  })) {
1234
1250
  }
1235
1251
 
1252
+ class EnvironmentApiKeysGroup extends HttpApiGroup4.make("environmentApiKeys").add(HttpApiEndpoint4.get("list", "/projects/:projectId/environments/:environment/api-keys", {
1253
+ params: environmentParams,
1254
+ success: Schema13.Array(EnvironmentApiKey),
1255
+ error: ReadErrors
1256
+ }), HttpApiEndpoint4.post("create", "/projects/:projectId/environments/:environment/api-keys", {
1257
+ params: environmentParams,
1258
+ payload: CreateEnvironmentApiKey,
1259
+ success: CreatedEnvironmentApiKey,
1260
+ error: WriteErrors
1261
+ }), HttpApiEndpoint4.delete("revoke", "/projects/:projectId/environments/:environment/api-keys/:keyId", {
1262
+ params: { ...environmentParams, keyId: Schema13.String },
1263
+ error: WriteErrors
1264
+ })) {
1265
+ }
1266
+
1236
1267
  class EnvironmentVariablesGroup extends HttpApiGroup4.make("environmentVariables").add(HttpApiEndpoint4.get("list", "/projects/:projectId/environments/:environment/variables", {
1237
1268
  params: environmentParams,
1238
1269
  success: Schema13.Array(EnvVariable),
@@ -1418,7 +1449,7 @@ class RuntimeGroup extends HttpApiGroup5.make("runtime").add(HttpApiEndpoint5.ge
1418
1449
  }
1419
1450
 
1420
1451
  // ../../packages/cloud-api/src/contract.ts
1421
- class CloudApi extends HttpApi.make("akter-cloud").add(AccountGroup, OrganizationsGroup, MembersGroup, InvitationsGroup, ApiKeysGroup, ProjectsGroup, EnvironmentVariablesGroup, DomainsGroup, RegionsGroup, IntegrationsGroup, DeploymentsGroup, RuntimeGroup, BillingGroup, UsageGroup, AuditGroup).middleware(Authentication).prefix("/api").annotateMerge(OpenApi3.annotations({ title: "Akter Cloud API" })) {
1452
+ class CloudApi extends HttpApi.make("akter-cloud").add(AccountGroup, OrganizationsGroup, MembersGroup, InvitationsGroup, ApiKeysGroup, ProjectsGroup, EnvironmentApiKeysGroup, EnvironmentVariablesGroup, DomainsGroup, RegionsGroup, IntegrationsGroup, DeploymentsGroup, RuntimeGroup, BillingGroup, UsageGroup, AuditGroup).middleware(Authentication).prefix("/api").annotateMerge(OpenApi3.annotations({ title: "Akter Cloud API" })) {
1422
1453
  }
1423
1454
  export {
1424
1455
  AccountGroup,
@@ -1469,10 +1500,12 @@ export {
1469
1500
  CreateApiKey,
1470
1501
  CreateDeployment,
1471
1502
  CreateEnvironment,
1503
+ CreateEnvironmentApiKey,
1472
1504
  CreateInvitation,
1473
1505
  CreateOrganization,
1474
1506
  CreateProject,
1475
1507
  CreatedApiKey,
1508
+ CreatedEnvironmentApiKey,
1476
1509
  CurrentIdentity,
1477
1510
  DeadLetter,
1478
1511
  DeadLetterId,
@@ -1494,6 +1527,9 @@ export {
1494
1527
  EnvVariable,
1495
1528
  EnvVariableName,
1496
1529
  Environment,
1530
+ EnvironmentApiKey,
1531
+ EnvironmentApiKeyTenant,
1532
+ EnvironmentApiKeysGroup,
1497
1533
  EnvironmentId,
1498
1534
  EnvironmentName,
1499
1535
  EnvironmentVariablesGroup,
@@ -31,7 +31,7 @@ export type UpdateProject = typeof UpdateProject.Type;
31
31
  * Every environment uses the customer's Postgres through `DATABASE_URL`.
32
32
  * `latency` is the deploy probe's p50 in milliseconds from the runner region,
33
33
  * null when unmeasured. Above 5 ms, `latencyWarning` warns without refusing.
34
- * `runnerCap` is floor((max_connections - in_use - 10) / 9), null when unknown;
34
+ * `runnerCap` is floor((max_connections - in_use - 10) / 4), null when unknown;
35
35
  * a non-positive cap means no runner fits the available connection budget.
36
36
  * The status carries no URL or URL-derived field.
37
37
  */
@@ -52,6 +52,36 @@ export declare const CreateEnvironment: Schema.Struct<{
52
52
  readonly name: Schema.Literals<readonly ["production", "staging", "dev"]>;
53
53
  }>;
54
54
  export type CreateEnvironment = typeof CreateEnvironment.Type;
55
+ /** The tenant a deployed application's key acts in. */
56
+ export declare const EnvironmentApiKeyTenant: Schema.String;
57
+ export type EnvironmentApiKeyTenant = typeof EnvironmentApiKeyTenant.Type;
58
+ /** An environment key's metadata; its secret is readable only at creation. */
59
+ export declare const EnvironmentApiKey: Schema.Struct<{
60
+ readonly id: Schema.String;
61
+ readonly name: Schema.String;
62
+ readonly tenant: Schema.String;
63
+ readonly createdAt: Schema.DateTimeUtc;
64
+ readonly revokedAt: Schema.NullOr<Schema.DateTimeUtc>;
65
+ }>;
66
+ export type EnvironmentApiKey = typeof EnvironmentApiKey.Type;
67
+ /** Omitting tenant creates a key for the default tenant. */
68
+ export declare const CreateEnvironmentApiKey: Schema.Struct<{
69
+ readonly name: Schema.brand<Schema.String, "Name">;
70
+ readonly tenant: Schema.optional<Schema.String>;
71
+ }>;
72
+ export type CreateEnvironmentApiKey = typeof CreateEnvironmentApiKey.Type;
73
+ /** The only environment-key response carrying the one-time secret. */
74
+ export declare const CreatedEnvironmentApiKey: Schema.Struct<{
75
+ readonly key: Schema.Struct<{
76
+ readonly id: Schema.String;
77
+ readonly name: Schema.String;
78
+ readonly tenant: Schema.String;
79
+ readonly createdAt: Schema.DateTimeUtc;
80
+ readonly revokedAt: Schema.NullOr<Schema.DateTimeUtc>;
81
+ }>;
82
+ readonly secret: Schema.String;
83
+ }>;
84
+ export type CreatedEnvironmentApiKey = typeof CreatedEnvironmentApiKey.Type;
55
85
  /** An environment variable as readable: its name and provenance, never its value or any part of it. */
56
86
  export declare const EnvVariable: Schema.Struct<{
57
87
  readonly name: Schema.String;
@@ -156,6 +186,7 @@ export declare const SetHomeRegion: Schema.Struct<{
156
186
  readonly region: Schema.Literals<readonly ["us-east-1", "us-west-2"]>;
157
187
  }>;
158
188
  export type SetHomeRegion = typeof SetHomeRegion.Type;
189
+ /** Public environment URLs; OpenAPI and MCP paths are empty when not advertised. */
159
190
  export declare const ProjectEndpoints: Schema.Struct<{
160
191
  readonly httpBaseUrl: Schema.String;
161
192
  readonly webSocketUrl: Schema.String;
package/dist/main.js CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/main.ts
4
- import { Context as Context2, Effect as Effect23, Layer as Layer5, Stdio as Stdio2 } from "effect";
4
+ import { Context as Context2, Effect as Effect24, Layer as Layer5, Stdio as Stdio2 } from "effect";
5
5
  import { FetchHttpClient } from "effect/http";
6
6
 
7
7
  // src/cli.ts
8
- import { Effect as Effect22, Runtime as Runtime2, Schema as Schema29 } from "effect";
9
- import { CliError, Command as Command19 } from "effect/cli";
8
+ import { Effect as Effect23, Runtime as Runtime2, Schema as Schema29 } from "effect";
9
+ import { CliError, Command as Command20 } from "effect/cli";
10
10
  // package.json
11
- var version = "0.1.0-alpha.4";
11
+ var version = "0.1.0-alpha.6";
12
12
 
13
13
  // src/commands/adopt/run.ts
14
14
  import {
@@ -1312,6 +1312,22 @@ var Environment = Schema13.Struct({
1312
1312
  }))
1313
1313
  });
1314
1314
  var CreateEnvironment = Schema13.Struct({ name: EnvironmentName });
1315
+ var EnvironmentApiKeyTenant = Schema13.String.check(Schema13.isPattern(/^[A-Za-z0-9._:-]{1,128}$/u));
1316
+ var EnvironmentApiKey = Schema13.Struct({
1317
+ id: Schema13.String,
1318
+ name: Schema13.String,
1319
+ tenant: Schema13.String,
1320
+ createdAt: Timestamp,
1321
+ revokedAt: Schema13.NullOr(Timestamp)
1322
+ });
1323
+ var CreateEnvironmentApiKey = Schema13.Struct({
1324
+ name: Name,
1325
+ tenant: Schema13.optional(EnvironmentApiKeyTenant)
1326
+ });
1327
+ var CreatedEnvironmentApiKey = Schema13.Struct({
1328
+ key: EnvironmentApiKey,
1329
+ secret: Schema13.String
1330
+ });
1315
1331
  var EnvVariable = Schema13.Struct({
1316
1332
  name: Schema13.String,
1317
1333
  usedBy: Schema13.Array(Schema13.String),
@@ -2227,6 +2243,21 @@ class ProjectsGroup extends HttpApiGroup4.make("projects").add(HttpApiEndpoint4.
2227
2243
  })) {
2228
2244
  }
2229
2245
 
2246
+ class EnvironmentApiKeysGroup extends HttpApiGroup4.make("environmentApiKeys").add(HttpApiEndpoint4.get("list", "/projects/:projectId/environments/:environment/api-keys", {
2247
+ params: environmentParams,
2248
+ success: Schema21.Array(EnvironmentApiKey),
2249
+ error: ReadErrors
2250
+ }), HttpApiEndpoint4.post("create", "/projects/:projectId/environments/:environment/api-keys", {
2251
+ params: environmentParams,
2252
+ payload: CreateEnvironmentApiKey,
2253
+ success: CreatedEnvironmentApiKey,
2254
+ error: WriteErrors
2255
+ }), HttpApiEndpoint4.delete("revoke", "/projects/:projectId/environments/:environment/api-keys/:keyId", {
2256
+ params: { ...environmentParams, keyId: Schema21.String },
2257
+ error: WriteErrors
2258
+ })) {
2259
+ }
2260
+
2230
2261
  class EnvironmentVariablesGroup extends HttpApiGroup4.make("environmentVariables").add(HttpApiEndpoint4.get("list", "/projects/:projectId/environments/:environment/variables", {
2231
2262
  params: environmentParams,
2232
2263
  success: Schema21.Array(EnvVariable),
@@ -2412,7 +2443,7 @@ class RuntimeGroup extends HttpApiGroup5.make("runtime").add(HttpApiEndpoint5.ge
2412
2443
  }
2413
2444
 
2414
2445
  // ../../packages/cloud-api/src/contract.ts
2415
- class CloudApi extends HttpApi.make("akter-cloud").add(AccountGroup, OrganizationsGroup, MembersGroup, InvitationsGroup, ApiKeysGroup, ProjectsGroup, EnvironmentVariablesGroup, DomainsGroup, RegionsGroup, IntegrationsGroup, DeploymentsGroup, RuntimeGroup, BillingGroup, UsageGroup, AuditGroup).middleware(Authentication).prefix("/api").annotateMerge(OpenApi3.annotations({ title: "Akter Cloud API" })) {
2446
+ class CloudApi extends HttpApi.make("akter-cloud").add(AccountGroup, OrganizationsGroup, MembersGroup, InvitationsGroup, ApiKeysGroup, ProjectsGroup, EnvironmentApiKeysGroup, EnvironmentVariablesGroup, DomainsGroup, RegionsGroup, IntegrationsGroup, DeploymentsGroup, RuntimeGroup, BillingGroup, UsageGroup, AuditGroup).middleware(Authentication).prefix("/api").annotateMerge(OpenApi3.annotations({ title: "Akter Cloud API" })) {
2416
2447
  }
2417
2448
  // src/commands/cloud/deploy.ts
2418
2449
  import { Clock as Clock3, Config as Config3, Console as Console9, Duration as Duration3, Effect as Effect16, Option as Option8, Schema as Schema26, Stream } from "effect";
@@ -3209,9 +3240,57 @@ var logsCommand = Command18.make("logs", {
3209
3240
  }
3210
3241
  }).pipe(reportFailures)).pipe(Command18.withDescription("Read recent customer runner logs, or follow with resumable long polls"));
3211
3242
 
3243
+ // src/commands/cloud/keys.ts
3244
+ import { Config as Config7, Console as Console15, DateTime as DateTime4, Effect as Effect22, Option as Option12 } from "effect";
3245
+ import { Argument as Argument7, Command as Command19, Flag as Flag16 } from "effect/cli";
3246
+ var colourSequence2 = new RegExp(`${String.fromCodePoint(27)}\\[[0-?]*[ -/]*[@-~]`, "gu");
3247
+ var metadata = (value) => value.replace(colourSequence2, "").replace(/\p{Cc}|[\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]/gu, "�");
3248
+ var scope2 = {
3249
+ project: Flag16.String("project").pipe(Flag16.withFallbackConfig(Config7.String("AKTER_PROJECT")), Flag16.withSchema(ProjectId), Flag16.withDescription("The project (default AKTER_PROJECT)")),
3250
+ environment: Flag16.Literals("env", EnvironmentName.literals).pipe(Flag16.withDefault("production"), Flag16.withDescription("The environment (default production)"))
3251
+ };
3252
+ var create = Command19.make("create", {
3253
+ ...scope2,
3254
+ name: Argument7.String("name").pipe(Argument7.withSchema(Name), Argument7.withDescription("The key's display name")),
3255
+ tenant: Flag16.String("tenant").pipe(Flag16.withSchema(EnvironmentApiKeyTenant), Flag16.optional, Flag16.withDescription("The application's tenant (default default)"))
3256
+ }, ({ project, environment, name, tenant }) => Effect22.gen(function* () {
3257
+ const { client } = yield* signedIn;
3258
+ const created = yield* client.environmentApiKeys.create({
3259
+ params: { projectId: project, environment },
3260
+ payload: Option12.isSome(tenant) ? { name, tenant: tenant.value } : { name }
3261
+ });
3262
+ yield* Console15.error(`Created ${metadata(created.key.id)} in ${metadata(environment)} for tenant ${metadata(created.key.tenant)}. Save the secret printed on stdout now; it cannot be read again.`);
3263
+ yield* Console15.log(created.secret);
3264
+ }).pipe(reportFailures)).pipe(Command19.withDescription("Create an environment key; print its one-time secret on stdout"));
3265
+ var list3 = Command19.make("list", scope2, ({ project, environment }) => Effect22.gen(function* () {
3266
+ const { client } = yield* signedIn;
3267
+ const keys = yield* client.environmentApiKeys.list({
3268
+ params: { projectId: project, environment }
3269
+ });
3270
+ for (const key of keys)
3271
+ yield* Console15.log([
3272
+ key.id,
3273
+ key.name,
3274
+ key.tenant,
3275
+ DateTime4.formatIso(key.createdAt),
3276
+ key.revokedAt === null ? "active" : DateTime4.formatIso(key.revokedAt)
3277
+ ].map(metadata).join("\t"));
3278
+ }).pipe(reportFailures)).pipe(Command19.withDescription("List key metadata, including revoked keys; never print secrets"));
3279
+ var revoke2 = Command19.make("revoke", {
3280
+ ...scope2,
3281
+ keyId: Argument7.String("keyId").pipe(Argument7.withDescription("The key id to revoke"))
3282
+ }, ({ project, environment, keyId }) => Effect22.gen(function* () {
3283
+ const { client } = yield* signedIn;
3284
+ yield* client.environmentApiKeys.revoke({
3285
+ params: { projectId: project, environment, keyId }
3286
+ });
3287
+ yield* Console15.log(`Revoked ${metadata(keyId)} in ${metadata(environment)}.`);
3288
+ }).pipe(reportFailures)).pipe(Command19.withDescription("Revoke an environment key"));
3289
+ var keysCommand = Command19.make("keys").pipe(Command19.withDescription("Manage Akter Cloud environment API keys for deployed applications"), Command19.withSubcommands([create, list3, revoke2]));
3290
+
3212
3291
  // src/cli.ts
3213
- var group = (name, description, subcommands) => Command19.make(name).pipe(Command19.withDescription(description), Command19.withSubcommands(subcommands));
3214
- var akter = Command19.make("akter").pipe(Command19.withDescription("Run actors locally, check a deploy against stored data, adopt existing tables, inspect and repair a running deployment, and deploy to Akter Cloud"), Command19.withSubcommands([
3292
+ var group = (name, description, subcommands) => Command20.make(name).pipe(Command20.withDescription(description), Command20.withSubcommands(subcommands));
3293
+ var akter = Command20.make("akter").pipe(Command20.withDescription("Run actors locally, check a deploy against stored data, adopt existing tables, inspect and repair a running deployment, and deploy to Akter Cloud"), Command20.withSubcommands([
3215
3294
  {
3216
3295
  group: "Develop and check",
3217
3296
  commands: [
@@ -3262,19 +3341,20 @@ var akter = Command19.make("akter").pipe(Command19.withDescription("Run actors l
3262
3341
  whoamiCommand,
3263
3342
  deployCommand,
3264
3343
  envCommand,
3344
+ keysCommand,
3265
3345
  logsCommand
3266
3346
  ]
3267
3347
  }
3268
3348
  ]));
3269
3349
  var isShowHelp = Schema29.is(CliError.ShowHelp);
3270
- var run2 = (args) => Command19.runWith(akter, { version })(args).pipe(Effect22.catchIf((error) => CliError.isCliError(error) && Runtime2.getErrorExitCode(error) !== 0, (error) => Effect22.fail(CommandFailed.make({
3350
+ var run2 = (args) => Command20.runWith(akter, { version })(args).pipe(Effect23.catchIf((error) => CliError.isCliError(error) && Runtime2.getErrorExitCode(error) !== 0, (error) => Effect23.fail(CommandFailed.make({
3271
3351
  exitCode: 2,
3272
3352
  reason: isShowHelp(error) ? error.errors[0]?._tag ?? "ShowHelp" : error._tag
3273
3353
  }))));
3274
3354
 
3275
3355
  // src/main.ts
3276
- Effect23.gen(function* () {
3356
+ Effect24.gen(function* () {
3277
3357
  const services = yield* Layer5.build(Layer5.mergeAll(PlatformServices.layer, FetchHttpClient.layer));
3278
3358
  const args = yield* Context2.get(services, Stdio2.Stdio).args;
3279
- return yield* run2(args).pipe(Effect23.provideContext(services));
3280
- }).pipe(Effect23.scoped, PlatformRuntime.runMain);
3359
+ return yield* run2(args).pipe(Effect24.provideContext(services));
3360
+ }).pipe(Effect24.scoped, PlatformRuntime.runMain);
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@rikalabs/akter-cli","version":"0.1.0-alpha.4","files":["dist","CHANGELOG.md","README.md","LICENSE","NOTICE"],"dependencies":{"@effect/platform-bun":"4.0.2","@effect/platform-node":"4.0.2","@rikalabs/akter":"0.1.0-alpha.4"},"peerDependencies":{"@effect/sql-pg":"^4.0.2","@effect/sql-pglite":"^4.0.2","drizzle-orm":"^1.0.0-rc.5-5935859","effect":"^4.0.2"},"bin":{"akter":"dist/main.js"},"publishConfig":{"access":"public"},"description":"The Akter command-line tool for local development and Akter Cloud","keywords":["actors","akter","durable","effect","pglite","postgres"],"homepage":"https://github.com/Rika-Labs/akter#readme","bugs":"https://github.com/Rika-Labs/akter/issues","license":"Apache-2.0","author":"Rika Labs","repository":{"type":"git","url":"git+https://github.com/Rika-Labs/akter.git","directory":"apps/cli"},"type":"module","types":"./dist/main.d.ts","exports":{".":{"types":"./dist/main.d.ts","default":"./dist/main.js"},"./cloud-api":{"types":"./dist/cloud-api/index.d.ts","default":"./dist/cloud-api/index.js"}},"engines":{"bun":">=1.4.2","node":">=24.0.0"}}
1
+ {"name":"@rikalabs/akter-cli","version":"0.1.0-alpha.6","files":["dist","CHANGELOG.md","README.md","LICENSE","NOTICE"],"dependencies":{"@effect/platform-bun":"4.0.2","@effect/platform-node":"4.0.2","@rikalabs/akter":"0.1.0-alpha.6"},"peerDependencies":{"@effect/sql-pg":"^4.0.2","@effect/sql-pglite":"^4.0.2","drizzle-orm":"^1.0.0-rc.5-5935859","effect":"^4.0.2"},"bin":{"akter":"dist/main.js"},"publishConfig":{"access":"public"},"description":"The Akter command-line tool for local development and Akter Cloud","keywords":["actors","akter","durable","effect","pglite","postgres"],"homepage":"https://github.com/Rika-Labs/akter#readme","bugs":"https://github.com/Rika-Labs/akter/issues","license":"Apache-2.0","author":"Rika Labs","repository":{"type":"git","url":"git+https://github.com/Rika-Labs/akter.git","directory":"apps/cli"},"type":"module","types":"./dist/main.d.ts","exports":{".":{"types":"./dist/main.d.ts","default":"./dist/main.js"},"./cloud-api":{"types":"./dist/cloud-api/index.d.ts","default":"./dist/cloud-api/index.js"}},"engines":{"bun":">=1.4.2","node":">=24.0.0"}}