@theholocron/holocron-plugin-github 5.0.0-alpha.433 → 5.0.0-alpha.435

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/dist/index.d.mts CHANGED
@@ -377,6 +377,12 @@ export declare function syncTeams(client: GitHubClient, repo: string, teams: Tea
377
377
  * Returns the base64 ciphertext to send as `encrypted_value`.
378
378
  */
379
379
  export declare function encryptSecret(publicKeyBase64: string, value: string): Promise<string>;
380
+ /**
381
+ * Every token this plugin takes, for `holocron doctor tokens`, with what each layer's token must and must not be able
382
+ * to do. The release token is `optional`: only CI's release workflow reads it (from the org secret), so a development
383
+ * environment has no reason to hold it.
384
+ */
385
+ export declare const tokens: PluginToken[];
380
386
  /** Options for `verifyToken`. */
381
387
  interface VerifyTokenOptions {
382
388
  /** Overrides the API base URL, for tests. */
@@ -432,6 +438,7 @@ export declare function projects(ctx: PluginContext): Projects;
432
438
  export declare function createPlugin(options: GitHubPluginOptions): {
433
439
  name: string;
434
440
  probes: {
441
+ token: import("@theholocron/cli").Probe;
435
442
  connection: import("@theholocron/cli").Probe;
436
443
  };
437
444
  capabilities: {
@@ -448,9 +455,4 @@ export declare function createPlugin(options: GitHubPluginOptions): {
448
455
  * is supplied or the supplied token is rejected.
449
456
  */
450
457
  export declare const AUTH_HINT: string;
451
- /**
452
- * Every token this plugin takes, for `holocron doctor secrets --verify`. The release token is `optional`: only CI's release
453
- * workflow reads it (from the org secret), so a development environment has no reason to hold it.
454
- */
455
- export declare const tokens: PluginToken[];
456
458
  export { type Auth, AuthError, type CanonicalLabel, type GitHubClientOptions, type NormalizedTeamEntry, type ProjectsOptions, type ResolveTokenInput, type TeamEntry, type TeamPermission, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, createFeatureResolver, createGitHubClient };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
- import { AuthError, MissingTokenError, ProviderApiError, connectionProbe, createFeatureResolver, pickByCreation, readKeysLimited, reportProgress } from "@theholocron/cli";
2
+ import { AuthError, MissingTokenError, ProviderApiError, connectionProbe, createFeatureResolver, pickByCreation, readKeysLimited, reportProgress, tokenExpectations } from "@theholocron/cli";
3
3
  import { createGitHubClient, createGitHubClient as createGitHubClient$1 } from "@theholocron/github-client";
4
4
  import { mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
5
5
  import { dirname, join } from "node:path";
@@ -2143,6 +2143,378 @@ async function ensureDir(path) {
2143
2143
  throw err;
2144
2144
  }
2145
2145
  }
2146
+ // src/probes/token/expectations.ts
2147
+ /** The same rules in every layer that runs the workflow: a laptop (`local` inherits `dev`) and CI. */
2148
+ function everywhere(rules) {
2149
+ return { permissions: {
2150
+ local: rules,
2151
+ dev: rules,
2152
+ ci: rules
2153
+ } };
2154
+ }
2155
+ /**
2156
+ * What each GitHub token is meant to carry, by its `envName`, the same as the GitHub tokens table in
2157
+ * `docs/src/content/docs/tokens.mdx`. This is the plugin's `tokens` declaration, read through `tokenExpectations()`;
2158
+ * change it and that table together.
2159
+ *
2160
+ * Every token CI uses (the `sync-repo`, `sync-secrets`, `reconcile-projects` and `check-tokens` workflows read all of
2161
+ * them) is declared with the same permissions in `local`, `dev` and `ci`, so the probe checks that a `ci` token is no
2162
+ * broader than its `dev` one rather than assuming a split the workflows do not allow. The release token is held by CI
2163
+ * only, so it has no `local` or `dev` entry. A narrow token must not reach administration or secrets; the admin token
2164
+ * must not reach organization secrets (that is `HOLOCRON_SECRETS_TOKEN`'s alone).
2165
+ */
2166
+ const EXPECTED = {
2167
+ HOLOCRON_READ_TOKEN: everywhere({
2168
+ contents: "required",
2169
+ actions: "required",
2170
+ administration: "absent",
2171
+ secrets: "absent",
2172
+ environments: "absent"
2173
+ }),
2174
+ HOLOCRON_ISSUES_TOKEN: everywhere({
2175
+ issues: "required",
2176
+ administration: "absent",
2177
+ secrets: "absent",
2178
+ environments: "absent"
2179
+ }),
2180
+ HOLOCRON_SYNC_TOKEN: everywhere({
2181
+ actions: "required",
2182
+ contents: "required",
2183
+ "pull-requests": "required",
2184
+ administration: "absent",
2185
+ secrets: "absent"
2186
+ }),
2187
+ HOLOCRON_RELEASE_TOKEN: { permissions: { ci: {
2188
+ contents: "required",
2189
+ issues: "required",
2190
+ "pull-requests": "required",
2191
+ administration: "absent",
2192
+ secrets: "absent"
2193
+ } } },
2194
+ HOLOCRON_ADMIN_TOKEN: everywhere({
2195
+ administration: "required",
2196
+ secrets: "required",
2197
+ environments: "required",
2198
+ issues: "required",
2199
+ "custom-properties": "required",
2200
+ "actions-variables": "required",
2201
+ "org-secrets": "absent"
2202
+ }),
2203
+ HOLOCRON_SECRETS_TOKEN: everywhere({
2204
+ "org-secrets": "required",
2205
+ administration: "absent"
2206
+ }),
2207
+ HOLOCRON_DEPLOY_TOKEN: everywhere({
2208
+ pages: "required",
2209
+ administration: "required",
2210
+ secrets: "absent",
2211
+ "org-secrets": "absent"
2212
+ }),
2213
+ HOLOCRON_USER_SYNC_TOKEN: everywhere({
2214
+ "user-sync-contents": "required",
2215
+ administration: "absent",
2216
+ secrets: "absent"
2217
+ }),
2218
+ HOLOCRON_ORG_TOKEN: everywhere({
2219
+ "org-administration": "required",
2220
+ "org-members": "required",
2221
+ "org-variables": "required",
2222
+ "org-secrets": "absent"
2223
+ })
2224
+ };
2225
+ // src/tokens.ts
2226
+ /** Adds what a layer's token must and must not be able to do (`EXPECTED`, by `envName`) to a token. */
2227
+ function declared(token) {
2228
+ return {
2229
+ ...token,
2230
+ expect: EXPECTED[token.envName]
2231
+ };
2232
+ }
2233
+ /**
2234
+ * Every token this plugin takes, for `holocron doctor tokens`, with what each layer's token must and must not be able
2235
+ * to do. The release token is `optional`: only CI's release workflow reads it (from the org secret), so a development
2236
+ * environment has no reason to hold it.
2237
+ */
2238
+ const tokens = [
2239
+ declared(resolveReadToken.token),
2240
+ declared(resolveIssuesToken.token),
2241
+ declared(resolveSyncToken.token),
2242
+ declared({
2243
+ ...resolveReleaseToken.token,
2244
+ optional: true
2245
+ }),
2246
+ declared(resolveAdminToken.token),
2247
+ declared(resolveSecretsToken.token),
2248
+ declared(resolveDeployToken.token),
2249
+ declared(resolveUserSyncToken.token),
2250
+ declared(resolveOrgToken.token)
2251
+ ];
2252
+ // src/probes/token/parse-token-args.ts
2253
+ /** Reads the words after the probe name: `--layer <word>` and `--token-name <VAR>`, in either spelling. */
2254
+ function parseTokenArgs(args) {
2255
+ let layer;
2256
+ let tokenName;
2257
+ for (let i = 0; i < args.length; i++) {
2258
+ const arg = args[i];
2259
+ if (arg === "--layer") layer = args[++i];
2260
+ else if (arg.startsWith("--layer=")) layer = arg.slice(8);
2261
+ else if (arg === "--token-name") tokenName = args[++i];
2262
+ else if (arg.startsWith("--token-name=")) tokenName = arg.slice(13);
2263
+ }
2264
+ return {
2265
+ ...layer ? { layer } : {},
2266
+ ...tokenName ? { tokenName } : {}
2267
+ };
2268
+ }
2269
+ // src/probes/token/permissions.ts
2270
+ /**
2271
+ * Every permission the GitHub plugin's tokens are declared against, by the name the declaration uses, with one read
2272
+ * that needs it. A read proves the token can see the area, not that it can write to it: GitHub exposes no list of a
2273
+ * fine-grained token's permissions, so the write half of `read/write` is taken from the permission table in
2274
+ * `docs/src/content/docs/tokens.mdx`. On a public repository the `contents`, `actions`, `issues` and `pull-requests`
2275
+ * reads succeed for any token, so only the other permissions can prove a permission absent. Names with more than one
2276
+ * word are hyphenated, not underscored: `holocron probe docs tokens` strips `_` (Markdown emphasis) from a table cell
2277
+ * before it compares the id with the declaration.
2278
+ */
2279
+ const PERMISSIONS = {
2280
+ contents: {
2281
+ label: "Contents",
2282
+ path: "/repos/{r}/contents"
2283
+ },
2284
+ actions: {
2285
+ label: "Actions",
2286
+ path: "/repos/{r}/actions/runs?per_page=1"
2287
+ },
2288
+ issues: {
2289
+ label: "Issues",
2290
+ path: "/repos/{r}/issues?per_page=1"
2291
+ },
2292
+ "pull-requests": {
2293
+ label: "Pull requests",
2294
+ path: "/repos/{r}/pulls?per_page=1"
2295
+ },
2296
+ administration: {
2297
+ label: "Administration",
2298
+ path: "/repos/{r}/actions/permissions"
2299
+ },
2300
+ secrets: {
2301
+ label: "Secrets",
2302
+ path: "/repos/{r}/actions/secrets?per_page=1"
2303
+ },
2304
+ environments: {
2305
+ label: "Environments",
2306
+ path: "/repos/{r}/environments?per_page=1"
2307
+ },
2308
+ "actions-variables": {
2309
+ label: "Variables",
2310
+ path: "/repos/{r}/actions/variables?per_page=1"
2311
+ },
2312
+ "custom-properties": {
2313
+ label: "Custom properties",
2314
+ path: "/repos/{r}/properties/values"
2315
+ },
2316
+ pages: {
2317
+ label: "Pages",
2318
+ path: "/repos/{r}/pages"
2319
+ },
2320
+ "org-administration": {
2321
+ label: "Organization: Administration",
2322
+ path: "/orgs/{o}/actions/permissions"
2323
+ },
2324
+ "org-members": {
2325
+ label: "Organization: Members",
2326
+ path: "/orgs/{o}/members?per_page=1"
2327
+ },
2328
+ "org-variables": {
2329
+ label: "Organization: Variables",
2330
+ path: "/orgs/{o}/actions/variables?per_page=1"
2331
+ },
2332
+ "org-secrets": {
2333
+ label: "Organization: Secrets",
2334
+ path: "/orgs/{o}/actions/secrets?per_page=1"
2335
+ },
2336
+ "user-sync-contents": {
2337
+ label: "Contents (.github-private)",
2338
+ path: "/repos/{o}/.github-private/contents"
2339
+ }
2340
+ };
2341
+ // src/probes/token/token.ts
2342
+ /** The token checked when none is named: the one the plugin reads with by default. */
2343
+ const DEFAULT_TOKEN = "HOLOCRON_READ_TOKEN";
2344
+ /** Does one GET with the token; the response headers are returned for the caller that wants them. */
2345
+ async function get(ctx, token, path) {
2346
+ return ctx.fetch(`${ctx.baseUrl}${path}`, { headers: {
2347
+ authorization: `Bearer ${token}`,
2348
+ accept: "application/vnd.github+json",
2349
+ "x-github-api-version": "2022-11-28",
2350
+ "user-agent": "holocron-probe"
2351
+ } });
2352
+ }
2353
+ /**
2354
+ * One read for one permission. GitHub answers a token without the permission with a 403, or a 404 for something it will
2355
+ * not admit exists, so both are `none`; a 2xx is `has`. Any other status, or a request that did not go through, is an
2356
+ * `error`, which is a failure whatever the layer expects.
2357
+ */
2358
+ async function reach(ctx, token, permission) {
2359
+ const [owner = ""] = ctx.repo.split("/");
2360
+ const path = PERMISSIONS[permission].path.replaceAll("{r}", ctx.repo).replaceAll("{o}", owner);
2361
+ try {
2362
+ const res = await get(ctx, token, path);
2363
+ if (res.ok) return {
2364
+ kind: "has",
2365
+ detail: `read ${path.split("?")[0]}`
2366
+ };
2367
+ if (res.status === 403 || res.status === 404) return {
2368
+ kind: "none",
2369
+ detail: `no access (${res.status})`
2370
+ };
2371
+ return {
2372
+ kind: "error",
2373
+ detail: `${res.status} ${res.statusText}`.trim()
2374
+ };
2375
+ } catch (err) {
2376
+ return {
2377
+ kind: "error",
2378
+ detail: errorMessage(err)
2379
+ };
2380
+ }
2381
+ }
2382
+ /**
2383
+ * One row for what was tried. With no rule it only describes (`ok` for access, `info` for none). Under a layer's rule it
2384
+ * judges: a required permission the token lacks fails, and one the layer must not have fails when the token has it; a
2385
+ * permission that is rightly absent is a bare `ok`.
2386
+ */
2387
+ function rowFor({ label, outcome }, rule) {
2388
+ if (outcome.kind === "error") return {
2389
+ status: "fail",
2390
+ label,
2391
+ detail: outcome.detail
2392
+ };
2393
+ const has = outcome.kind === "has";
2394
+ if (rule === "required") return {
2395
+ status: has ? "ok" : "fail",
2396
+ label,
2397
+ detail: outcome.detail
2398
+ };
2399
+ if (rule === "absent") return has ? {
2400
+ status: "fail",
2401
+ label,
2402
+ detail: outcome.detail
2403
+ } : {
2404
+ status: "ok",
2405
+ label
2406
+ };
2407
+ return {
2408
+ status: has ? "ok" : "info",
2409
+ label,
2410
+ detail: outcome.detail
2411
+ };
2412
+ }
2413
+ /**
2414
+ * The `token` probe: `holocron probe github token` tries each permission Holocron uses with one of the plugin's nine
2415
+ * tokens and reports which ones the token reaches. It only reads (one GET per permission), so it changes nothing, and a
2416
+ * read proves the token can see an area, not that it can write there.
2417
+ *
2418
+ * GitHub lists scopes only for a classic token (the `X-OAuth-Scopes` header on any response), so a classic token's scopes
2419
+ * are shown. A fine-grained token has no list, so the permissions are found by trying them; the first row says which kind
2420
+ * was read. With `--environment <layer>` the CLI runs the probe once for each token the Environment holds and hands it
2421
+ * `--token-name <envName>` (and the token itself as `cliToken`); by hand, `--token-name` picks which token the plugin
2422
+ * resolves (default `HOLOCRON_READ_TOKEN`).
2423
+ *
2424
+ * With no layer the token is only described. When the CLI passes `--layer` (because `--environment` named `ci`, `dev` or
2425
+ * `local`), the results are judged against what that token is meant to carry in that layer (the plugin's `tokens`
2426
+ * declaration, read with `tokenExpectations()`) and shown in two groups, what it should have and what it should not,
2427
+ * where a missing or extra permission fails.
2428
+ */
2429
+ function tokenProbe(ctx) {
2430
+ return {
2431
+ summary: "Try each GitHub permission Holocron uses (contents, actions, issues, administration, secrets, ...) with one of the plugin's tokens and report which it reaches; for a ci or dev Environment, check it against what that layer should carry. Read-only.",
2432
+ writes: false,
2433
+ acceptsToken: true,
2434
+ async run(probe) {
2435
+ const { layer, tokenName } = parseTokenArgs(probe.args ?? []);
2436
+ const envName = tokenName ?? DEFAULT_TOKEN;
2437
+ const token = ctx.resolve(envName);
2438
+ if (token === void 0) {
2439
+ probe.say({
2440
+ status: "fail",
2441
+ label: envName,
2442
+ detail: `not a GitHub token; use one of: ${ctx.tokenNames.join(", ")}`
2443
+ });
2444
+ return;
2445
+ }
2446
+ probe.secret(token);
2447
+ let identity;
2448
+ try {
2449
+ identity = await get(ctx, token, "/user");
2450
+ } catch (err) {
2451
+ probe.say({
2452
+ status: "fail",
2453
+ label: "token",
2454
+ detail: errorMessage(err)
2455
+ });
2456
+ return;
2457
+ }
2458
+ if (identity.status === 401) {
2459
+ probe.say({
2460
+ status: "fail",
2461
+ label: "token",
2462
+ detail: "rejected by GitHub (401): expired, revoked or not a token"
2463
+ });
2464
+ return;
2465
+ }
2466
+ const scopes = identity.headers.get("x-oauth-scopes");
2467
+ probe.say({
2468
+ status: "ok",
2469
+ label: "token",
2470
+ detail: scopes === null ? "fine-grained (GitHub lists no permissions for one, so each is tried with a read)" : `classic (scopes: ${scopes === "" ? "none" : scopes}); each permission is also tried with a read`
2471
+ });
2472
+ const declared = layer ? tokenExpectations(tokens, {
2473
+ layer,
2474
+ envName
2475
+ })[0] : void 0;
2476
+ if (layer && !declared) probe.say({
2477
+ status: "info",
2478
+ label: layer,
2479
+ detail: "no expectations are declared for this token there, so it is only described"
2480
+ });
2481
+ const rules = declared?.rules ?? {};
2482
+ const names = declared ? Object.keys(rules) : Object.keys(PERMISSIONS);
2483
+ const tried = [];
2484
+ for (const permission of names) tried.push({
2485
+ label: PERMISSIONS[permission].label,
2486
+ permission,
2487
+ outcome: await reach(ctx, token, permission)
2488
+ });
2489
+ if (!declared) {
2490
+ for (const t of tried) probe.say(rowFor(t, void 0));
2491
+ return;
2492
+ }
2493
+ for (const [heading, rule] of [["Should have", "required"], ["Should not have", "absent"]]) {
2494
+ const inGroup = tried.filter((t) => rules[t.permission] === rule);
2495
+ if (inGroup.length === 0) continue;
2496
+ probe.say({
2497
+ status: "heading",
2498
+ label: heading
2499
+ });
2500
+ for (const t of inGroup) probe.say(rowFor(t, rule));
2501
+ }
2502
+ }
2503
+ };
2504
+ }
2505
+ // src/token-resolvers.ts
2506
+ /** Each token's resolver by its environment variable (`HOLOCRON_ADMIN_TOKEN`), which is what `--token-name` carries. */
2507
+ const TOKEN_RESOLVERS = {
2508
+ HOLOCRON_READ_TOKEN: resolveReadToken,
2509
+ HOLOCRON_ISSUES_TOKEN: resolveIssuesToken,
2510
+ HOLOCRON_SYNC_TOKEN: resolveSyncToken,
2511
+ HOLOCRON_RELEASE_TOKEN: resolveReleaseToken,
2512
+ HOLOCRON_ADMIN_TOKEN: resolveAdminToken,
2513
+ HOLOCRON_SECRETS_TOKEN: resolveSecretsToken,
2514
+ HOLOCRON_DEPLOY_TOKEN: resolveDeployToken,
2515
+ HOLOCRON_USER_SYNC_TOKEN: resolveUserSyncToken,
2516
+ HOLOCRON_ORG_TOKEN: resolveOrgToken
2517
+ };
2146
2518
  // src/verify-token.ts
2147
2519
  /** Checks a token against `GET /user` and returns who it belongs to, or why it failed. */
2148
2520
  async function verifyToken(token, opts = {}) {
@@ -2271,16 +2643,25 @@ function createPlugin(options) {
2271
2643
  }
2272
2644
  return {
2273
2645
  name: "@theholocron/holocron-plugin-github",
2274
- probes: { connection: connectionProbe({
2275
- provider: "GitHub",
2276
- url: options.baseUrl ?? "https://api.github.com",
2277
- fetch: options.fetch,
2278
- token: () => resolveReadToken(options),
2279
- verify: (token) => verifyToken(token, {
2280
- baseUrl: options.baseUrl,
2281
- fetch: options.fetch
2646
+ probes: {
2647
+ token: tokenProbe({
2648
+ repo: options.repo,
2649
+ baseUrl: (options.baseUrl ?? "https://api.github.com").replace(/\/$/, ""),
2650
+ fetch: options.fetch ?? fetch,
2651
+ resolve: (envName) => TOKEN_RESOLVERS[envName]?.(options),
2652
+ tokenNames: Object.keys(TOKEN_RESOLVERS)
2653
+ }),
2654
+ connection: connectionProbe({
2655
+ provider: "GitHub",
2656
+ url: options.baseUrl ?? "https://api.github.com",
2657
+ fetch: options.fetch,
2658
+ token: () => resolveReadToken(options),
2659
+ verify: (token) => verifyToken(token, {
2660
+ baseUrl: options.baseUrl,
2661
+ fetch: options.fetch
2662
+ })
2282
2663
  })
2283
- }) },
2664
+ },
2284
2665
  capabilities: {
2285
2666
  source: () => source(makeCtx(resolveAdminToken), makeOrgClient(), makeUserSyncClient()),
2286
2667
  ci: () => ci(makeCtx(resolveReadToken)),
@@ -2296,22 +2677,4 @@ function createPlugin(options) {
2296
2677
  * is supplied or the supplied token is rejected.
2297
2678
  */
2298
2679
  const AUTH_HINT = "generate fine-grained Personal Access Tokens at https://github.com/settings/tokens (one per feature — see docs/tokens.md for required scopes per operation), then run: holocron new token github.<feature> <PAT>";
2299
- /**
2300
- * Every token this plugin takes, for `holocron doctor secrets --verify`. The release token is `optional`: only CI's release
2301
- * workflow reads it (from the org secret), so a development environment has no reason to hold it.
2302
- */
2303
- const tokens = [
2304
- resolveReadToken.token,
2305
- resolveIssuesToken.token,
2306
- resolveSyncToken.token,
2307
- {
2308
- ...resolveReleaseToken.token,
2309
- optional: true
2310
- },
2311
- resolveAdminToken.token,
2312
- resolveSecretsToken.token,
2313
- resolveDeployToken.token,
2314
- resolveUserSyncToken.token,
2315
- resolveOrgToken.token
2316
- ];
2317
2680
  export { AUTH_HINT, AuthError, GitHubCi, GitHubEnvironments, GitHubIssues, GitHubProjects, GitHubSecrets, GitHubSource, ci, createFeatureResolver, createGitHubClient, createPlugin, encryptSecret, environments, issues, normalizeTeamEntry, projects, resolveAdminToken, resolveDeployToken, resolveIssuesToken, resolveOrgToken, resolveReadToken, resolveReleaseToken, resolveSecretsToken, resolveSyncToken, resolveUserSyncToken, secrets, source, syncLabels, syncTeams, tokens, verifyToken };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/holocron-plugin-github",
3
- "version": "5.0.0-alpha.433",
3
+ "version": "5.0.0-alpha.435",
4
4
  "description": "Holocron plugin for GitHub. Implements source, ci, secrets, environments, and issues capabilities against the GitHub REST API.",
5
5
  "keywords": [
6
6
  "ci",
@@ -44,21 +44,21 @@
44
44
  "tsx": "4.23.15",
45
45
  "typescript": "^5.9.3",
46
46
  "vitest": "^5.1.0",
47
- "@theholocron/cli": "5.0.0-alpha.433",
48
- "@theholocron/eslint-config": "^8.9.0-alpha.17",
49
47
  "@theholocron/fs-utils": "^1.17.0-alpha.4",
50
- "@theholocron/http-client": "^1.58.0-alpha.29",
48
+ "@theholocron/github-client": "^1.58.0-alpha.31",
49
+ "@theholocron/cli": "5.0.0-alpha.435",
51
50
  "@theholocron/misc-utils": "^1.17.0-alpha.4",
52
- "@theholocron/github-client": "^1.58.0-alpha.29",
51
+ "@theholocron/http-client": "^1.58.0-alpha.31",
52
+ "@theholocron/tsconfig": "^8.9.0-alpha.17",
53
53
  "@theholocron/tsdown-config": "^8.9.0-alpha.17",
54
54
  "@theholocron/vitest-config": "^8.9.0-alpha.17",
55
- "@theholocron/tsconfig": "^8.9.0-alpha.17"
55
+ "@theholocron/eslint-config": "^8.9.0-alpha.17"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "@theholocron/fs-utils": "^1.16.0",
59
59
  "@theholocron/github-client": "^1.58.0",
60
60
  "@theholocron/misc-utils": "^1.16.0",
61
- "@theholocron/cli": "5.0.0-alpha.433"
61
+ "@theholocron/cli": "5.0.0-alpha.435"
62
62
  },
63
63
  "engines": {
64
64
  "node": ">=22"