@gjermundgaraba/clankercreds 0.3.0 → 0.4.0

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.
@@ -1,4 +1,4 @@
1
- import { a as NeedsSignIn, d as ProviderUnavailable, i as Name, l as scopes, n as Conflict, o as NotFound, r as Host, s as UpstreamUnavailable, u as CurrentPrincipal } from "./shared-DBK2cCkw.mjs";
1
+ import { a as LoginKind, c as NotFound, f as scopes, i as Host, l as SecretKind, m as ProviderUnavailable, n as Conflict, o as Name, p as CurrentPrincipal, s as NeedsSignIn, u as UpstreamUnavailable } from "./shared-C56uw1xx.mjs";
2
2
  import { Config, Console, Effect, Option, Redacted, Schema } from "effect";
3
3
  import * as Action from "@gjermundgaraba/effect-actions/Action";
4
4
  import * as ActionHttp from "@gjermundgaraba/effect-actions/ActionHttp";
@@ -12,8 +12,6 @@ import * as ActionCli from "@gjermundgaraba/effect-actions/ActionCli";
12
12
  //#region ../../packages/api/src/admin.ts
13
13
  /** Written by the service, always ISO. What an operator enters is decoded as a date instead. */
14
14
  const Timestamp = Schema.String;
15
- /** The kinds an operator stores a value for. A ChatGPT login only ever comes from a sign-in. */
16
- const SecretKind = Schema.Literals(["gh", "claude"]);
17
15
  /** A stored secret's state. The value itself is never read back out. */
18
16
  const SecretStatus = Schema.Struct({
19
17
  name: Name,
@@ -24,20 +22,21 @@ const SecretStatus = Schema.Struct({
24
22
  createdAt: Timestamp,
25
23
  updatedAt: Timestamp
26
24
  });
27
- /** A ChatGPT login's state. It exists from the first completed sign-in on. */
28
- const ChatgptStatus = Schema.Struct({
25
+ /** A login's state. It exists from the first completed sign-in on. */
26
+ const LoginStatus = Schema.Struct({
29
27
  name: Name,
30
- kind: Schema.Literal("chatgpt"),
28
+ kind: LoginKind,
31
29
  needsSignIn: Schema.Boolean,
32
30
  email: Schema.NullOr(Schema.String),
33
- accountId: Schema.String,
31
+ /** The ChatGPT account a ChatGPT login is for; null for every other kind. */
32
+ accountId: Schema.NullOr(Schema.String),
34
33
  accessExpiresAt: Timestamp,
35
34
  lastRefreshAt: Timestamp,
36
35
  lastError: Schema.NullOr(Schema.String),
37
36
  createdAt: Timestamp,
38
37
  updatedAt: Timestamp
39
38
  });
40
- const CredentialStatus = Schema.Union([SecretStatus, ChatgptStatus]);
39
+ const CredentialStatus = Schema.Union([SecretStatus, LoginStatus]);
41
40
  /** The clankerauth id of a machine key. */
42
41
  const KeyId = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(256));
43
42
  /**
@@ -65,16 +64,21 @@ const ClaudeSignIn = Schema.Struct({
65
64
  * `authorizeUrl`. An approval that left out a scope the token needs ends it: start again.
66
65
  */
67
66
  var SignInRefused = class extends Schema.TaggedError()("SignInRefused", { message: Schema.String }, { httpApiStatus: 422 }) {};
67
+ /**
68
+ * A login's sign-in: open `verificationUrl` and approve, entering `userCode` where the
69
+ * provider asks for one. Cursor's link carries everything and has no code.
70
+ */
68
71
  const SignInState = Schema.Struct({
69
72
  signInId: Schema.String,
70
73
  credential: Name,
74
+ kind: LoginKind,
71
75
  status: Schema.Literals([
72
76
  "pending",
73
77
  "complete",
74
78
  "failed",
75
79
  "expired"
76
80
  ]),
77
- userCode: Schema.String,
81
+ userCode: Schema.NullOr(Schema.String),
78
82
  verificationUrl: Schema.String,
79
83
  expiresAt: Timestamp,
80
84
  message: Schema.optionalKey(Schema.String)
@@ -108,10 +112,10 @@ const AuditQuery = Schema.Struct({
108
112
  clientId: Schema.optionalKey(Schema.String)
109
113
  });
110
114
  /**
111
- * A read whose user code signs a ChatGPT account in: exported so the server's authorization
115
+ * A read whose code or link signs an account in: exported so the server's authorization
112
116
  * rule can name it.
113
117
  */
114
- const GetChatgptSignIn = Action.make("getChatgptSignIn", {
118
+ const GetSignIn = Action.make("getSignIn", {
115
119
  readOnly: true,
116
120
  caller: CurrentPrincipal,
117
121
  description: "Read a sign-in. The service holds one in memory only, until the next sign-in starts after it expired; one it no longer holds is not found.",
@@ -124,13 +128,13 @@ const Admin = [
124
128
  Action.make("listCredentials", {
125
129
  readOnly: true,
126
130
  caller: CurrentPrincipal,
127
- description: "Every credential with its state: expiry, last refresh, last error and whether a ChatGPT login needs a new sign-in. Values are never returned.",
131
+ description: "Every credential with its state: expiry, last refresh, last error and whether a login needs a new sign-in. Values are never returned.",
128
132
  success: Schema.Struct({ credentials: Schema.Array(CredentialStatus) })
129
133
  }),
130
134
  Action.make("putCredential", {
131
135
  readOnly: false,
132
136
  caller: CurrentPrincipal,
133
- description: "Store a secret under a name, or replace its value and expiry. A `gh` token is for `host`, github.com unless given. A credential's kind and host never change; remove it and put it again instead. Machines receive it on their next sync.",
137
+ description: "Store a secret under a name, or replace its value and expiry: a `gh` or `claude` token a machine places, or a `token`, any other service's API key, which a service such as clankerusage reads. A `gh` token is for `host`, github.com unless given. A credential's kind and host never change; remove it and put it again instead. Keys granted it receive it on their next sync.",
134
138
  input: Schema.Struct({
135
139
  name: Name,
136
140
  kind: SecretKind,
@@ -153,21 +157,24 @@ const Admin = [
153
157
  success: Schema.Void,
154
158
  error: [NotFound, Conflict]
155
159
  }),
156
- Action.make("startChatgptSignIn", {
160
+ Action.make("startSignIn", {
157
161
  readOnly: false,
158
162
  caller: CurrentPrincipal,
159
- description: "Start a device-code sign-in for a ChatGPT credential; the credential is created, or its login replaced, when the sign-in completes. Approve the code at the returned URL, then poll getChatgptSignIn.",
160
- input: Schema.Struct({ name: Name }),
163
+ description: "Start a sign-in for a ChatGPT, Grok or Cursor login; the credential is created, or its login replaced, when the sign-in completes. Open the returned verificationUrl and approve, entering userCode where one is given, then poll getSignIn.",
164
+ input: Schema.Struct({
165
+ name: Name,
166
+ kind: LoginKind
167
+ }),
161
168
  success: SignInState,
162
169
  error: [Conflict, UpstreamUnavailable]
163
170
  }),
164
- GetChatgptSignIn,
165
- Action.make("refreshChatgptCredential", {
171
+ GetSignIn,
172
+ Action.make("refreshCredential", {
166
173
  readOnly: false,
167
174
  caller: CurrentPrincipal,
168
- description: "Refresh one ChatGPT login now instead of waiting for its schedule.",
175
+ description: "Refresh one login now instead of waiting for its schedule.",
169
176
  input: Schema.Struct({ name: Name }),
170
- success: ChatgptStatus,
177
+ success: LoginStatus,
171
178
  error: [
172
179
  NotFound,
173
180
  Conflict,
@@ -236,7 +243,7 @@ const AdminHttp = ActionHttp.make(Admin, {
236
243
  });
237
244
  //#endregion
238
245
  //#region package.json
239
- var version = "0.3.0";
246
+ var version = "0.4.0";
240
247
  //#endregion
241
248
  //#region src/admin.ts
242
249
  /** A refusal of this command's own, printed as its message on stderr, exiting 1. */
@@ -299,7 +306,7 @@ const json = (value) => Console.log(JSON.stringify(value, null, 2));
299
306
  /** `putCredential`, its value read from stdin and every other field a flag. */
300
307
  const putCredential = Command.make("put-credential", {
301
308
  name: Flag.String("name").pipe(Flag.withDescription("The credential's name")),
302
- kind: Flag.Literals("kind", SecretKind.literals).pipe(Flag.withDescription("The tool the secret is for")),
309
+ kind: Flag.Literals("kind", SecretKind.literals).pipe(Flag.withDescription("What the secret is: a gh or claude token a machine places, or a token, any other service's API key")),
303
310
  host: Flag.String("host").pipe(Flag.withDescription("A gh token's host; github.com when left out"), Flag.optional),
304
311
  expiresAt: Flag.String("expires-at").pipe(Flag.withDescription("When the secret expires, any date string; it never does when left out"), Flag.optional)
305
312
  }, ({ name, kind, host, expiresAt }) => Effect.gen(function* () {
package/dist/main.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as NeedsSignIn, c as claimsOf, d as ProviderUnavailable, i as Name, o as NotFound, s as UpstreamUnavailable, t as ClientId, u as CurrentPrincipal } from "./shared-DBK2cCkw.mjs";
2
+ import { c as NotFound, d as claimsOf, m as ProviderUnavailable, o as Name, p as CurrentPrincipal, r as CredentialKind, s as NeedsSignIn, t as ClientId, u as UpstreamUnavailable } from "./shared-C56uw1xx.mjs";
3
3
  import { homedir } from "node:os";
4
4
  import { dirname, join } from "node:path";
5
5
  import { Effect, Option, Predicate, Schema } from "effect";
@@ -11,8 +11,16 @@ import { randomBytes } from "node:crypto";
11
11
  import { HttpClient, HttpClientRequest } from "effect/http";
12
12
  import { YAMLMap, isMap, parseDocument } from "yaml";
13
13
  //#region ../../packages/api/src/credentials.ts
14
- /** The credential an entry was delivered from, as the machine asked for it by name. */
15
- const fromCredential = { credential: Name };
14
+ /**
15
+ * The credential an entry was delivered from, as it was asked for by name, and when what it
16
+ * carries expires, as ISO: a secret's as the operator entered it, a login's access token's
17
+ * own. Null never expires. A login delivered past it could not be renewed in time, as when its
18
+ * provider is away: sync again later. Whether it needs a new sign-in is the operator's to see.
19
+ */
20
+ const fromCredential = {
21
+ credential: Name,
22
+ expiresAt: Schema.NullOr(Schema.String)
23
+ };
16
24
  const GhCredential = Schema.Struct({
17
25
  type: Schema.Literal("gh"),
18
26
  ...fromCredential,
@@ -48,6 +56,16 @@ const PiCredential = Schema.Struct({
48
56
  accessToken: Schema.String
49
57
  });
50
58
  /**
59
+ * A credential no machine places: an API key, or a Grok or Cursor login's access token, for
60
+ * a service such as clankerusage that knows which provider each name is for. A machine
61
+ * whose config names one refuses the sync.
62
+ */
63
+ const TokenCredential = Schema.Struct({
64
+ type: Schema.Literal("token"),
65
+ ...fromCredential,
66
+ token: Schema.String
67
+ });
68
+ /**
51
69
  * The service sends typed credentials, never file contents or paths, so it cannot write
52
70
  * anything on a machine but what the client knows how to place. The cost is that a new
53
71
  * tool, or a placement fix, needs a client release, which new machines install. Each entry
@@ -64,7 +82,8 @@ const TypedCredential = Schema.Union([
64
82
  GhCredential,
65
83
  ClaudeCredential,
66
84
  CodexCredential,
67
- PiCredential
85
+ PiCredential,
86
+ TokenCredential
68
87
  ]);
69
88
  /** The types this build knows, derived from the union so there is one list. */
70
89
  const knownTypes = TypedCredential.members.map((member) => member.fields.type.literal);
@@ -75,39 +94,54 @@ const isKnownType = (type) => knownTypes.some((known) => known === type);
75
94
  * schema must not land here, or a broken credential would be placed as an empty one.
76
95
  */
77
96
  const UnknownCredential = Schema.Struct({ type: Schema.String.check(Schema.makeFilter((type) => !isKnownType(type), { message: "a known credential type must match its schema" })) });
78
- /** Everything the machine asked for, sent in full on every sync. */
97
+ /** Everything the caller asked for, sent in full on every sync. */
79
98
  const Delivery = Schema.Struct({ credentials: Schema.Array(Schema.Union([TypedCredential, UnknownCredential])) });
80
99
  //#endregion
81
100
  //#region ../../packages/api/src/machine.ts
101
+ /** A credential the calling key may read, without its value. */
102
+ const Grant = Schema.Struct({
103
+ name: Name,
104
+ kind: CredentialKind
105
+ });
82
106
  /**
83
107
  * What a machine key can do: read the credentials it is granted, by name, and nothing else.
84
- * The machine names what it wants; the grants on the server decide whether it may.
108
+ * The caller names what it wants; the grants on the server decide whether it may. A machine
109
+ * is one caller; a service such as clankerusage, holding a key of its own, is another.
85
110
  */
86
- const Machine = [Action.make("sync", {
87
- readOnly: false,
88
- caller: CurrentPrincipal,
89
- description: "Fetch the named credentials as typed entries. Refused whole when the calling key is not granted any one of them.",
90
- input: Schema.Struct({
91
- clientId: ClientId,
92
- credentials: Schema.Array(Name)
111
+ const Machine = [
112
+ Action.make("sync", {
113
+ readOnly: false,
114
+ caller: CurrentPrincipal,
115
+ description: "Fetch the named credentials as typed entries, each with its expiry; a login near expiry is refreshed first. Refused whole when the calling key is not granted any one of them.",
116
+ input: Schema.Struct({
117
+ clientId: ClientId,
118
+ credentials: Schema.Array(Name)
119
+ }),
120
+ success: Delivery,
121
+ error: NotFound
93
122
  }),
94
- success: Delivery,
95
- error: NotFound
96
- }), Action.make("codexLogin", {
97
- readOnly: false,
98
- caller: CurrentPrincipal,
99
- description: "The current login of a ChatGPT credential the calling key is granted, as the codex type carries it, refreshed first when it has expired.",
100
- input: Schema.Struct({
101
- clientId: ClientId,
102
- credential: Name
123
+ Action.make("codexLogin", {
124
+ readOnly: false,
125
+ caller: CurrentPrincipal,
126
+ description: "The current login of a ChatGPT credential the calling key is granted, as the codex type carries it, refreshed first when it has expired.",
127
+ input: Schema.Struct({
128
+ clientId: ClientId,
129
+ credential: Name
130
+ }),
131
+ success: CodexLogin,
132
+ error: [
133
+ NotFound,
134
+ NeedsSignIn,
135
+ UpstreamUnavailable
136
+ ]
103
137
  }),
104
- success: CodexLogin,
105
- error: [
106
- NotFound,
107
- NeedsSignIn,
108
- UpstreamUnavailable
109
- ]
110
- })];
138
+ Action.make("listGrants", {
139
+ readOnly: true,
140
+ caller: CurrentPrincipal,
141
+ description: "The names and kinds of the credentials the calling key is granted, so a caller can offer them to pick from. Values are never returned.",
142
+ success: Schema.Struct({ credentials: Schema.Array(Grant) })
143
+ })
144
+ ];
111
145
  /**
112
146
  * Codex treats a 401 as permanent and stops retrying; every other failure is transient.
113
147
  * The codes are the ones Codex classifies: `refresh_token_invalidated` reads as revoked.
@@ -582,6 +616,9 @@ const placements = {
582
616
  remove: (config) => removePi(config.home)
583
617
  }
584
618
  };
619
+ /** What this client places; anything else delivered, a token or a type it does not know, is skipped. */
620
+ const isPlaceable = (credential) => Object.hasOwn(placements, credential.type);
621
+ const placeableTypes = knownTypes.filter((type) => Object.hasOwn(placements, type));
585
622
  /** What the delivery carries of one type is placed; a type it does not carry is undone. */
586
623
  const settle = (config, identity, known, type) => {
587
624
  const credentials = known.filter((credential) => credential.type === type);
@@ -602,16 +639,17 @@ const slot = (credential) => {
602
639
  }
603
640
  };
604
641
  /**
605
- * Two credentials for one slot would leave the machine holding whichever came last, so the
642
+ * Two credentials for one slot would leave the machine holding whichever came last: the
606
643
  * whole sync is refused before anything is written.
607
644
  */
608
- const refuseShared = (known) => {
645
+ const oneEach = (placed) => {
609
646
  const claimed = /* @__PURE__ */ new Map();
610
- for (const credential of known) {
647
+ for (const credential of placed) {
611
648
  const other = claimed.get(slot(credential));
612
649
  if (other !== void 0 && other !== credential.credential) throw new Error(`${other} and ${credential.credential} are both ${slot(credential)}; a machine holds one, so config.json must name only one of them`);
613
650
  claimed.set(slot(credential), credential.credential);
614
651
  }
652
+ return placed;
615
653
  };
616
654
  /**
617
655
  * Idempotent: every credential the config names is fetched and placed every time, and every
@@ -626,15 +664,14 @@ const sync = async (config) => {
626
664
  key: config.key
627
665
  };
628
666
  const delivery = await fetchDelivery(config, identity.clientId);
629
- const known = delivery.credentials.filter((credential) => isKnownType(credential.type));
630
- refuseShared(known);
667
+ const known = oneEach(delivery.credentials.filter(isPlaceable));
631
668
  const report = {
632
669
  placed: new Array(),
633
670
  removed: new Array(),
634
- skipped: delivery.credentials.flatMap(({ type }) => isKnownType(type) ? [] : [type]),
671
+ skipped: delivery.credentials.flatMap((credential) => isPlaceable(credential) ? [] : [credential.type]),
635
672
  failed: new Array()
636
673
  };
637
- for (const type of knownTypes) try {
674
+ for (const type of placeableTypes) try {
638
675
  const outcome = settle(config, identity, known, type);
639
676
  if (outcome !== void 0) report[outcome].push(type);
640
677
  } catch (error) {
@@ -684,7 +721,7 @@ const usage = `Usage: clankercreds <command>
684
721
  `;
685
722
  const runSync = async () => {
686
723
  const report = await sync(loadConfig());
687
- for (const type of report.skipped) console.error(`warning: skipped unknown credential type "${type}"; update clankercreds`);
724
+ for (const type of report.skipped) console.error(`warning: skipped credential type "${type}", which this client does not place; if it is new, update clankercreds`);
688
725
  for (const type of report.placed) console.log(`placed ${type}`);
689
726
  for (const type of report.removed) console.log(`removed ${type}`);
690
727
  for (const { type, message } of report.failed) console.error(`error: ${type}: ${message}`);
@@ -704,7 +741,7 @@ const commandFor = (name) => {
704
741
  };
705
742
  const main = async () => {
706
743
  if (process.argv[2] === "admin") {
707
- (await import("./admin-CXDLXpaH.mjs")).run(process.argv.slice(2));
744
+ (await import("./admin-DC0cTmmT.mjs")).run(process.argv.slice(2));
708
745
  return;
709
746
  }
710
747
  const command = commandFor(process.argv[2]);
@@ -16,7 +16,7 @@ var ProviderUnavailable = class extends Schema.TaggedError()("ProviderUnavailabl
16
16
  Data.TaggedError("InsufficientScope");
17
17
  Schema.TaggedError()("ConfigurationError", { message: Schema.String });
18
18
  //#endregion
19
- //#region ../../node_modules/.pnpm/@gjermundgaraba+clankerauth-sdk@0.15.0_@gjermundgaraba+effect-actions@0.11.0_effect@4.0.2__effect@4.0.2/node_modules/@gjermundgaraba/clankerauth-sdk/dist/session.js
19
+ //#region ../../node_modules/.pnpm/@gjermundgaraba+clankerauth-sdk@0.16.0_@gjermundgaraba+effect-actions@0.11.0_effect@4.0.2__effect@4.0.2/node_modules/@gjermundgaraba/clankerauth-sdk/dist/session.js
20
20
  /**
21
21
  * The identity a browser page needs, without any verification code. This entry point is
22
22
  * browser-safe: it declares the identity a protected contract states, the `whoami` contract
@@ -62,9 +62,9 @@ const scopes = {
62
62
  var NotFound = class extends Schema.TaggedError()("NotFound", { message: Schema.String }, { httpApiStatus: 404 }) {};
63
63
  /** The change collides with what is stored: a taken name, or a credential still in use. */
64
64
  var Conflict = class extends Schema.TaggedError()("Conflict", { message: Schema.String }, { httpApiStatus: 409 }) {};
65
- /** The ChatGPT login is dead, or was never completed. Only a new device sign-in revives it. */
65
+ /** The login is dead, or was never completed. Only a new sign-in revives it. */
66
66
  var NeedsSignIn = class extends Schema.TaggedError()("NeedsSignIn", { message: Schema.String }, { httpApiStatus: 409 }) {};
67
- /** OpenAI could not be reached and no valid token is held. Waiting helps; retrying now does not. */
67
+ /** The provider could not be reached and no valid token is held. Waiting helps; retrying now does not. */
68
68
  var UpstreamUnavailable = class extends Schema.TaggedError()("UpstreamUnavailable", { message: Schema.String }, { httpApiStatus: 503 }) {};
69
69
  /**
70
70
  * Credential names: lowercase labels, because they are typed by hand and are
@@ -72,6 +72,25 @@ var UpstreamUnavailable = class extends Schema.TaggedError()("UpstreamUnavailabl
72
72
  * and `github-main` be two credentials.
73
73
  */
74
74
  const Name = Schema.String.check(Schema.isPattern(/^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/));
75
+ /**
76
+ * What an operator stores a value for: a GitHub token, a Claude token, or `token`, any other
77
+ * service's API key, which a service such as clankerusage reads and no machine places.
78
+ */
79
+ const SecretKind = Schema.Literals([
80
+ "gh",
81
+ "claude",
82
+ "token"
83
+ ]);
84
+ /**
85
+ * What a sign-in creates and the service keeps refreshed. The refresh token never leaves
86
+ * the service; only access tokens are delivered.
87
+ */
88
+ const LoginKind = Schema.Literals([
89
+ "chatgpt",
90
+ "grok",
91
+ "cursor"
92
+ ]);
93
+ const CredentialKind = Schema.Literals([...SecretKind.literals, ...LoginKind.literals]);
75
94
  /** A GitHub host, lowercase: it is written into `gh`'s and git's configuration as is. */
76
95
  const Host = Schema.String.check(Schema.isPattern(/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*$/), Schema.isMaxLength(253));
77
96
  /**
@@ -85,7 +104,7 @@ const Claims = Schema.Struct({
85
104
  "https://api.openai.com/auth": Schema.optionalKey(Schema.Struct({ chatgpt_account_id: Schema.optionalKey(Schema.String) }))
86
105
  });
87
106
  /**
88
- * The claims of an OpenAI JWT, unverified: they are read for their timing and their
107
+ * The claims of a JWT, unverified: they are read for their timing, email and, in OpenAI's,
89
108
  * account, never trusted for anything. Anything unreadable is simply no claims.
90
109
  */
91
110
  const claimsOf = (jwt) => {
@@ -105,4 +124,4 @@ const claimsOf = (jwt) => {
105
124
  });
106
125
  };
107
126
  //#endregion
108
- export { NeedsSignIn as a, claimsOf as c, ProviderUnavailable as d, Name as i, scopes as l, Conflict as n, NotFound as o, Host as r, UpstreamUnavailable as s, ClientId as t, CurrentPrincipal as u };
127
+ export { LoginKind as a, NotFound as c, claimsOf as d, scopes as f, Host as i, SecretKind as l, ProviderUnavailable as m, Conflict as n, Name as o, CurrentPrincipal as p, CredentialKind as r, NeedsSignIn as s, ClientId as t, UpstreamUnavailable as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjermundgaraba/clankercreds",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "The clankercreds command: a machine client that fetches the credentials its config names and places each where its tool expects it, and the operator's admin commands.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -20,14 +20,15 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@effect/platform-node": "4.0.2",
23
+ "@effect/platform-node-shared": "4.0.2",
23
24
  "@gjermundgaraba/effect-actions": "0.11.0",
24
25
  "effect": "4.0.2",
25
26
  "yaml": "2.9.1"
26
27
  },
27
28
  "devDependencies": {
28
- "@clankercreds/api": "0.0.0",
29
- "@gjermundgaraba/clankerauth-sdk": "0.15.0",
30
- "@types/node": "26.6.4",
29
+ "@gjermundgaraba/clankerauth-sdk": "0.16.0",
30
+ "@gjermundgaraba/clankercreds-api": "0.4.0",
31
+ "@types/node": "26.6.5",
31
32
  "typescript": "7.0.2",
32
33
  "vite": "npm:@voidzero-dev/vite-plus-core@1.1.0",
33
34
  "vite-plus": "1.1.0"