@effected/github 0.26.0 → 0.27.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.
- package/ActionsOidc.js +7 -4
- package/GitHubApp.js +71 -68
- package/README.md +3 -3
- package/index.d.ts +13 -9
- package/package.json +7 -7
- package/tsdoc-metadata.json +1 -1
package/ActionsOidc.js
CHANGED
|
@@ -143,7 +143,8 @@ const testClaims = (overrides = {}) => ({
|
|
|
143
143
|
* @remarks
|
|
144
144
|
* {@link ActionsOidc.verify} is `@effected/oidc`'s `Oidc.verify` pinned to the
|
|
145
145
|
* Actions issuer: it checks the signature against GitHub's published JWKS
|
|
146
|
-
* (through `@effected/jwt`'s `JwksResolver`, which caches it
|
|
146
|
+
* (through `@effected/jwt`'s `JwksResolver`, which caches it; the signature
|
|
147
|
+
* itself runs on core `effect/jose` and needs core's `Signature` service), then `iss`,
|
|
147
148
|
* `aud`, `exp`, `nbf` and `iat`, then decodes the payload into
|
|
148
149
|
* {@link ActionsOidcClaims}. Every failure is a `JwtError`; route on its
|
|
149
150
|
* `reason` (`wrongAudience`, `expired`, `claims`, ...), never on its message.
|
|
@@ -168,7 +169,8 @@ const testClaims = (overrides = {}) => ({
|
|
|
168
169
|
* ```ts
|
|
169
170
|
* import { JwksResolver } from "@effected/jwt";
|
|
170
171
|
* import { ActionsOidc } from "@effected/github";
|
|
171
|
-
* import { Data, Effect } from "effect";
|
|
172
|
+
* import { Data, Effect, Layer } from "effect";
|
|
173
|
+
* import { SecureRandom, Signature } from "effect/crypto";
|
|
172
174
|
*
|
|
173
175
|
* class Forbidden extends Data.TaggedError("Forbidden")<{ readonly repositoryId: number }> {}
|
|
174
176
|
*
|
|
@@ -186,7 +188,8 @@ const testClaims = (overrides = {}) => ({
|
|
|
186
188
|
* });
|
|
187
189
|
*
|
|
188
190
|
* // JwksResolver.layer needs an HttpClient and a JwksStore, provided once at the edge.
|
|
189
|
-
*
|
|
191
|
+
* const CryptoLive = Signature.layerWebCrypto.pipe(Layer.provide(SecureRandom.layerWebCrypto));
|
|
192
|
+
* export const program = authorize("eyJ...").pipe(Effect.provide(Layer.merge(JwksResolver.layer, CryptoLive)));
|
|
190
193
|
* ```
|
|
191
194
|
*
|
|
192
195
|
* @public
|
|
@@ -195,7 +198,7 @@ var ActionsOidc = class {
|
|
|
195
198
|
constructor() {}
|
|
196
199
|
/** The Actions OIDC issuer, `https://token.actions.githubusercontent.com`. */
|
|
197
200
|
static issuer = ISSUER;
|
|
198
|
-
/** Verify a runner-issued OIDC token: signature against GitHub's JWKS, iss, aud, exp/nbf, then typed claims
|
|
201
|
+
/** Verify a runner-issued OIDC token: signature against GitHub's JWKS, iss, aud, exp/nbf, then typed claims; requires `JwksResolver` and core `Signature`. */
|
|
199
202
|
static verify = verify;
|
|
200
203
|
/**
|
|
201
204
|
* A valid claims payload for tests, overridable field by field.
|
package/GitHubApp.js
CHANGED
|
@@ -7,6 +7,7 @@ import { numericId } from "./internal/ids.js";
|
|
|
7
7
|
import { InstallationTokenStore } from "./InstallationTokenStore.js";
|
|
8
8
|
import { Cause, Clock, Context, DateTime, Deferred, Duration, Effect, Layer, Option, Redacted, Ref, Schema, Semaphore, Stream } from "effect";
|
|
9
9
|
import { Jwt, JwtKey } from "@effected/jwt";
|
|
10
|
+
import { Signature } from "effect/crypto";
|
|
10
11
|
|
|
11
12
|
// src/GitHubApp.ts
|
|
12
13
|
/**
|
|
@@ -355,7 +356,7 @@ var GitHubApp = class GitHubApp extends Context.Service()("@effected/github/GitH
|
|
|
355
356
|
* Effect.runPromise(Effect.provide(sweep, layer));
|
|
356
357
|
* ```
|
|
357
358
|
*/
|
|
358
|
-
static appClientLayer = (credentials, options = {}) => Layer.effect(GitHubClient, makeRotatingClient(mintJwt(credentials), () => Effect.void, options, "GitHubApp.appClientLayer"));
|
|
359
|
+
static appClientLayer = (credentials, options = {}) => Layer.effect(GitHubClient, Effect.flatMap(Effect.service(Signature.Signature), (signature) => makeRotatingClient(Effect.provideService(mintJwt(credentials), Signature.Signature, signature), () => Effect.void, options, "GitHubApp.appClientLayer")));
|
|
359
360
|
/**
|
|
360
361
|
* An installation token, reused from an {@link InstallationTokenStore}
|
|
361
362
|
* while it has `margin` (five minutes by default) left to live.
|
|
@@ -534,7 +535,7 @@ const mintJwt = (credentials) => Effect.gen(function* () {
|
|
|
534
535
|
};
|
|
535
536
|
}).pipe(Effect.catchTag("JwtError", (error) => Effect.fail(GitHubAppError.of("jwt", error.detail, error))));
|
|
536
537
|
/** A client speaking as the app itself. */
|
|
537
|
-
const
|
|
538
|
+
const appClientOf = (credentials, options) => Effect.flatMap(mintJwt(credentials), ({ token }) => makeClientShape({
|
|
538
539
|
...options,
|
|
539
540
|
token
|
|
540
541
|
}));
|
|
@@ -545,75 +546,77 @@ const asBearer = (token, options) => makeClientShape({
|
|
|
545
546
|
});
|
|
546
547
|
const appFailure = (kind) => (error) => Effect.fail(GitHubAppError.of(kind, error.reason, error));
|
|
547
548
|
function makeApp(options) {
|
|
548
|
-
return Effect.map(resolveApiVersion(options.apiVersion), () =>
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
549
|
+
return Effect.flatMap(Effect.service(Signature.Signature), (signature) => Effect.map(resolveApiVersion(options.apiVersion), () => makeAppWith(options, signature)));
|
|
550
|
+
}
|
|
551
|
+
function makeAppWith(options, signature) {
|
|
552
|
+
const asApp = (credentials, clientOptions) => Effect.provideService(appClientOf(credentials, clientOptions), Signature.Signature, signature);
|
|
553
|
+
const installations = Effect.fn("GitHubApp.installations")(function* (credentials) {
|
|
554
|
+
return (yield* (yield* asApp(credentials, options)).paginate("GET /app/installations", {}).pipe(Effect.catch(appFailure("installation")))).map((entry) => {
|
|
555
|
+
const account = entry.account ?? void 0;
|
|
556
|
+
return Installation.make({
|
|
557
|
+
id: numericId(entry.id),
|
|
558
|
+
...account !== void 0 && typeof account.login === "string" ? { account: account.login } : {},
|
|
559
|
+
...readField("accountType", Schema.String, account?.type),
|
|
560
|
+
...readField("accountId", Schema.Int, typeof account?.id === "bigint" ? numericId(account.id) : account?.id),
|
|
561
|
+
...readField("suspendedAt", SuspendedAt, entry.suspended_at),
|
|
562
|
+
...readField("updatedAt", Schema.DateTimeUtcFromString, entry.updated_at)
|
|
560
563
|
});
|
|
561
564
|
});
|
|
562
|
-
const resolveInstallationId = (request) => request.installationId !== void 0 ? Effect.succeed(request.installationId) : Effect.gen(function* () {
|
|
563
|
-
const all = yield* installations(request);
|
|
564
|
-
if (request.owner !== void 0) {
|
|
565
|
-
const wanted = request.owner.toLowerCase();
|
|
566
|
-
const match = all.find((entry) => entry.account?.toLowerCase() === wanted);
|
|
567
|
-
if (match !== void 0) return match.id;
|
|
568
|
-
return yield* Effect.fail(GitHubAppError.of("installation", `the app is not installed on ${request.owner} (installed on: ${all.map((entry) => entry.account ?? entry.id).join(", ") || "nothing"})`));
|
|
569
|
-
}
|
|
570
|
-
const only = all[0];
|
|
571
|
-
if (all.length === 1 && only !== void 0) return only.id;
|
|
572
|
-
return yield* Effect.fail(GitHubAppError.of("installation", all.length === 0 ? "the app has no installations" : `the app has ${all.length} installations; pass installationId or owner`));
|
|
573
|
-
});
|
|
574
|
-
const token = Effect.fn("GitHubApp.token")(function* (request) {
|
|
575
|
-
const installationId = yield* resolveInstallationId(request);
|
|
576
|
-
const minted = yield* (yield* asApp(request, options)).request("POST /app/installations/{installation_id}/access_tokens", { installation_id: installationId }).pipe(Effect.catch(appFailure("token")));
|
|
577
|
-
return yield* Schema.decodeUnknownEffect(InstallationToken)({
|
|
578
|
-
token: minted.token,
|
|
579
|
-
expiresAt: minted.expires_at,
|
|
580
|
-
installationId,
|
|
581
|
-
permissions: normalizePermissions(minted.permissions)
|
|
582
|
-
}).pipe(Effect.catchTag("SchemaError", (error) => Effect.fail(GitHubAppError.of("token", "GitHub returned an unexpected token payload", error))));
|
|
583
|
-
});
|
|
584
|
-
const revoke = Effect.fn("GitHubApp.revoke")(function* (value) {
|
|
585
|
-
yield* (yield* asBearer(value, options)).request("DELETE /installation/token", {}).pipe(Effect.catch(appFailure("revoke")));
|
|
586
|
-
});
|
|
587
|
-
const scopedToken = (request) => Effect.acquireRelease(token(request), (minted) => Effect.ignore(revoke(minted.token)));
|
|
588
|
-
return {
|
|
589
|
-
token,
|
|
590
|
-
scopedToken,
|
|
591
|
-
revoke,
|
|
592
|
-
identity: Effect.fn("GitHubApp.identity")(function* (request) {
|
|
593
|
-
const app = yield* (yield* asApp(request, options)).request("GET /app", {}).pipe(Effect.catch(appFailure("identity")));
|
|
594
|
-
if (app === null) return yield* Effect.fail(GitHubAppError.of("identity", "GET /app returned no app"));
|
|
595
|
-
const slug = app.slug ?? "";
|
|
596
|
-
const name = app.name;
|
|
597
|
-
const user = yield* (yield* asBearer(request.installationToken, options)).request("GET /users/{username}", { username: `${slug}[bot]` }).pipe(Effect.option);
|
|
598
|
-
return AppIdentity.make({
|
|
599
|
-
slug,
|
|
600
|
-
name,
|
|
601
|
-
...Option.isSome(user) ? { userId: numericId(user.value.id) } : {}
|
|
602
|
-
});
|
|
603
|
-
}),
|
|
604
|
-
botUser: Effect.fn("GitHubApp.botUser")(function* (request) {
|
|
605
|
-
yield* Effect.annotateCurrentSpan({ slug: request.slug });
|
|
606
|
-
const user = yield* (yield* asBearer(request.installationToken, options)).request("GET /users/{username}", { username: `${request.slug}[bot]` }).pipe(Effect.catch(appFailure("identity")));
|
|
607
|
-
const raw = user;
|
|
608
|
-
return yield* Schema.decodeUnknownEffect(BotUser)(typeof raw === "object" && raw !== null ? {
|
|
609
|
-
id: numericId(user.id),
|
|
610
|
-
login: user.login
|
|
611
|
-
} : raw).pipe(Effect.catchTag("SchemaError", (error) => Effect.fail(GitHubAppError.of("identity", "GitHub returned an unexpected bot user", error))));
|
|
612
|
-
}),
|
|
613
|
-
installations,
|
|
614
|
-
cachedToken: makeCachedToken(token)
|
|
615
|
-
};
|
|
616
565
|
});
|
|
566
|
+
const resolveInstallationId = (request) => request.installationId !== void 0 ? Effect.succeed(request.installationId) : Effect.gen(function* () {
|
|
567
|
+
const all = yield* installations(request);
|
|
568
|
+
if (request.owner !== void 0) {
|
|
569
|
+
const wanted = request.owner.toLowerCase();
|
|
570
|
+
const match = all.find((entry) => entry.account?.toLowerCase() === wanted);
|
|
571
|
+
if (match !== void 0) return match.id;
|
|
572
|
+
return yield* Effect.fail(GitHubAppError.of("installation", `the app is not installed on ${request.owner} (installed on: ${all.map((entry) => entry.account ?? entry.id).join(", ") || "nothing"})`));
|
|
573
|
+
}
|
|
574
|
+
const only = all[0];
|
|
575
|
+
if (all.length === 1 && only !== void 0) return only.id;
|
|
576
|
+
return yield* Effect.fail(GitHubAppError.of("installation", all.length === 0 ? "the app has no installations" : `the app has ${all.length} installations; pass installationId or owner`));
|
|
577
|
+
});
|
|
578
|
+
const token = Effect.fn("GitHubApp.token")(function* (request) {
|
|
579
|
+
const installationId = yield* resolveInstallationId(request);
|
|
580
|
+
const minted = yield* (yield* asApp(request, options)).request("POST /app/installations/{installation_id}/access_tokens", { installation_id: installationId }).pipe(Effect.catch(appFailure("token")));
|
|
581
|
+
return yield* Schema.decodeUnknownEffect(InstallationToken)({
|
|
582
|
+
token: minted.token,
|
|
583
|
+
expiresAt: minted.expires_at,
|
|
584
|
+
installationId,
|
|
585
|
+
permissions: normalizePermissions(minted.permissions)
|
|
586
|
+
}).pipe(Effect.catchTag("SchemaError", (error) => Effect.fail(GitHubAppError.of("token", "GitHub returned an unexpected token payload", error))));
|
|
587
|
+
});
|
|
588
|
+
const revoke = Effect.fn("GitHubApp.revoke")(function* (value) {
|
|
589
|
+
yield* (yield* asBearer(value, options)).request("DELETE /installation/token", {}).pipe(Effect.catch(appFailure("revoke")));
|
|
590
|
+
});
|
|
591
|
+
const scopedToken = (request) => Effect.acquireRelease(token(request), (minted) => Effect.ignore(revoke(minted.token)));
|
|
592
|
+
return {
|
|
593
|
+
token,
|
|
594
|
+
scopedToken,
|
|
595
|
+
revoke,
|
|
596
|
+
identity: Effect.fn("GitHubApp.identity")(function* (request) {
|
|
597
|
+
const app = yield* (yield* asApp(request, options)).request("GET /app", {}).pipe(Effect.catch(appFailure("identity")));
|
|
598
|
+
if (app === null) return yield* Effect.fail(GitHubAppError.of("identity", "GET /app returned no app"));
|
|
599
|
+
const slug = app.slug ?? "";
|
|
600
|
+
const name = app.name;
|
|
601
|
+
const user = yield* (yield* asBearer(request.installationToken, options)).request("GET /users/{username}", { username: `${slug}[bot]` }).pipe(Effect.option);
|
|
602
|
+
return AppIdentity.make({
|
|
603
|
+
slug,
|
|
604
|
+
name,
|
|
605
|
+
...Option.isSome(user) ? { userId: numericId(user.value.id) } : {}
|
|
606
|
+
});
|
|
607
|
+
}),
|
|
608
|
+
botUser: Effect.fn("GitHubApp.botUser")(function* (request) {
|
|
609
|
+
yield* Effect.annotateCurrentSpan({ slug: request.slug });
|
|
610
|
+
const user = yield* (yield* asBearer(request.installationToken, options)).request("GET /users/{username}", { username: `${request.slug}[bot]` }).pipe(Effect.catch(appFailure("identity")));
|
|
611
|
+
const raw = user;
|
|
612
|
+
return yield* Schema.decodeUnknownEffect(BotUser)(typeof raw === "object" && raw !== null ? {
|
|
613
|
+
id: numericId(user.id),
|
|
614
|
+
login: user.login
|
|
615
|
+
} : raw).pipe(Effect.catchTag("SchemaError", (error) => Effect.fail(GitHubAppError.of("identity", "GitHub returned an unexpected bot user", error))));
|
|
616
|
+
}),
|
|
617
|
+
installations,
|
|
618
|
+
cachedToken: makeCachedToken(token)
|
|
619
|
+
};
|
|
617
620
|
}
|
|
618
621
|
/** GitHub's permission values are strings; anything else is not a permission. */
|
|
619
622
|
const normalizePermissions = (raw) => {
|
package/README.md
CHANGED
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
Typed GitHub REST and GraphQL for [Effect](https://effect.website) v4. `client.request("GET /repos/{owner}/{repo}", { owner, repo })` types both the parameters and the returned `data` from the route literal alone — no `operation: string`, no callback, no cast. One `GitHubError` covers every REST failure with a `kind` you branch on instead of grepping a message, one pagination engine backs every paginating route and `client.request`'s `Stream` form, and a set of resource services (`GitBranch`, `GitTag`, `CheckRun`, `PullRequest`, `PullRequestComment`, `GitHubRelease`, `Attestation`) turn multi-call dances — "does this branch already exist?", "conclude this check run no matter how the program exits" — into one call. A second tier writes the configuration half: secrets, variables, rulesets, deployment environments, the security toggles and CodeQL default setup. `GitHubApp` mints and revokes installation tokens for App auth.
|
|
9
9
|
|
|
10
10
|
> **Pre-`1.0.0`.** This package is part of the `@effected/*` kit, built on stable
|
|
11
|
-
> Effect v4 (`effect`
|
|
11
|
+
> Effect v4 (`effect` `~4.1.0`) and still in `0.x` development. Stable Effect
|
|
12
12
|
> makes a kit `1.0.0` possible, not automatic. To keep your `effect` and
|
|
13
13
|
> `@effect/*` versions on the line the kit is built and tested against, install
|
|
14
|
-
> [`@effected/pnpm-plugin-
|
|
14
|
+
> [`@effected/pnpm-plugin-effected`](https://www.npmjs.com/package/@effected/pnpm-plugin-effected).
|
|
15
15
|
>
|
|
16
16
|
> **Stability: unstable.** This package's API surface is not yet considered
|
|
17
17
|
> complete and may change across `0.x` releases. Pin an exact version — even a
|
|
@@ -25,7 +25,7 @@ Hand-rolled octokit wrappers tend to converge on the same shape: a `rest<T>(oper
|
|
|
25
25
|
|
|
26
26
|
The error model gets the same treatment. `GitHubError.kind` is a literal union (`notFound`, `alreadyExists`, `rejected`, `unauthorized`, `rateLimited`, `transport`, `decode`) produced by one classification step, `GitHubError.fromOctokit`, instead of one hand-written mapper per resource. `kind: "alreadyExists"` is what makes `GitBranch.upsert` and `GitTag.upsert` a single round trip in the common case, rather than a create-then-catch-then-check-then-reset dance repeated at every call site that needs it.
|
|
27
27
|
|
|
28
|
-
This package also owns the octokit runtime so nothing downstream has to. `@octokit/rest` and `@octokit/auth-app` are deliberately absent — the rest wrapper is a request-logging plugin plus 1.4 MB of duplicate endpoint types, and `auth-app` drags in `createOAuthUserAuth`, roughly 492 KB of OAuth machinery this package never calls. GitHub App JWTs are signed by the kit's own `@effected/jwt` instead
|
|
28
|
+
This package also owns the octokit runtime so nothing downstream has to. `@octokit/rest` and `@octokit/auth-app` are deliberately absent — the rest wrapper is a request-logging plugin plus 1.4 MB of duplicate endpoint types, and `auth-app` drags in `createOAuthUserAuth`, roughly 492 KB of OAuth machinery this package never calls. GitHub App JWTs are signed by the kit's own `@effected/jwt` instead, over core `effect/jose`: RS256 with no extra runtime dependencies, so App auth runs on Cloudflare Workers as well as Node. The App layers (`GitHubApp.layer`, `layerWith`, `clientLayer`, `appClientLayer`) require core's `Signature` service; provide `Signature.layerWebCrypto.pipe(Layer.provide(SecureRandom.layerWebCrypto))` from `effect/crypto` once at the edge. A consumer that only authenticates with a token it already holds never links the JWT signer at all: the App-authenticated layer lives in its own module (`GitHubApp`), and nothing here is gathered into a namespace object that would defeat that split.
|
|
29
29
|
|
|
30
30
|
## Install
|
|
31
31
|
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BareLineReference, CLOSING_KEYWORDS, ClosingKeyword, IssueReference, harvestIssueReferences, parseBareLineReference } from "@effected/github-references";
|
|
2
2
|
import { JwksResolver, JwtError } from "@effected/jwt";
|
|
3
3
|
import { Cause, Config, Context, Duration, Effect, Layer, Option, Redacted, Result, Schedule, Schema, Scope, Stream } from "effect";
|
|
4
|
+
import { Signature } from "effect/crypto";
|
|
4
5
|
import { PaginatingEndpoints } from "@octokit/plugin-paginate-rest";
|
|
5
6
|
import { Endpoints, RequestHeaders } from "@octokit/types";
|
|
6
7
|
import { SemVer } from "@effected/semver";
|
|
@@ -126,7 +127,8 @@ interface ActionsOidcVerifyOptions {
|
|
|
126
127
|
* @remarks
|
|
127
128
|
* {@link ActionsOidc.verify} is `@effected/oidc`'s `Oidc.verify` pinned to the
|
|
128
129
|
* Actions issuer: it checks the signature against GitHub's published JWKS
|
|
129
|
-
* (through `@effected/jwt`'s `JwksResolver`, which caches it
|
|
130
|
+
* (through `@effected/jwt`'s `JwksResolver`, which caches it; the signature
|
|
131
|
+
* itself runs on core `effect/jose` and needs core's `Signature` service), then `iss`,
|
|
130
132
|
* `aud`, `exp`, `nbf` and `iat`, then decodes the payload into
|
|
131
133
|
* {@link ActionsOidcClaims}. Every failure is a `JwtError`; route on its
|
|
132
134
|
* `reason` (`wrongAudience`, `expired`, `claims`, ...), never on its message.
|
|
@@ -151,7 +153,8 @@ interface ActionsOidcVerifyOptions {
|
|
|
151
153
|
* ```ts
|
|
152
154
|
* import { JwksResolver } from "@effected/jwt";
|
|
153
155
|
* import { ActionsOidc } from "@effected/github";
|
|
154
|
-
* import { Data, Effect } from "effect";
|
|
156
|
+
* import { Data, Effect, Layer } from "effect";
|
|
157
|
+
* import { SecureRandom, Signature } from "effect/crypto";
|
|
155
158
|
*
|
|
156
159
|
* class Forbidden extends Data.TaggedError("Forbidden")<{ readonly repositoryId: number }> {}
|
|
157
160
|
*
|
|
@@ -169,7 +172,8 @@ interface ActionsOidcVerifyOptions {
|
|
|
169
172
|
* });
|
|
170
173
|
*
|
|
171
174
|
* // JwksResolver.layer needs an HttpClient and a JwksStore, provided once at the edge.
|
|
172
|
-
*
|
|
175
|
+
* const CryptoLive = Signature.layerWebCrypto.pipe(Layer.provide(SecureRandom.layerWebCrypto));
|
|
176
|
+
* export const program = authorize("eyJ...").pipe(Effect.provide(Layer.merge(JwksResolver.layer, CryptoLive)));
|
|
173
177
|
* ```
|
|
174
178
|
*
|
|
175
179
|
* @public
|
|
@@ -178,8 +182,8 @@ export declare class ActionsOidc {
|
|
|
178
182
|
private constructor();
|
|
179
183
|
/** The Actions OIDC issuer, `https://token.actions.githubusercontent.com`. */
|
|
180
184
|
static readonly issuer: "https://token.actions.githubusercontent.com";
|
|
181
|
-
/** Verify a runner-issued OIDC token: signature against GitHub's JWKS, iss, aud, exp/nbf, then typed claims
|
|
182
|
-
static readonly verify: (token: string, options: ActionsOidcVerifyOptions) => Effect.Effect<ActionsOidcClaims, JwtError, JwksResolver>;
|
|
185
|
+
/** Verify a runner-issued OIDC token: signature against GitHub's JWKS, iss, aud, exp/nbf, then typed claims; requires `JwksResolver` and core `Signature`. */
|
|
186
|
+
static readonly verify: (token: string, options: ActionsOidcVerifyOptions) => Effect.Effect<ActionsOidcClaims, JwtError, JwksResolver | Signature.Signature>;
|
|
183
187
|
/**
|
|
184
188
|
* A valid claims payload for tests, overridable field by field.
|
|
185
189
|
*
|
|
@@ -2848,7 +2852,7 @@ declare const GitHubApp_base: Context.ServiceClass<GitHubApp, "@effected/github/
|
|
|
2848
2852
|
*/
|
|
2849
2853
|
export declare class GitHubApp extends GitHubApp_base {
|
|
2850
2854
|
/** The default transport. Bind it once; layers are memoized by reference. */
|
|
2851
|
-
static readonly layer: Layer.Layer<GitHubApp>;
|
|
2855
|
+
static readonly layer: Layer.Layer<GitHubApp, never, Signature.Signature>;
|
|
2852
2856
|
/**
|
|
2853
2857
|
* A transport with custom settings.
|
|
2854
2858
|
*
|
|
@@ -2857,7 +2861,7 @@ export declare class GitHubApp extends GitHubApp_base {
|
|
|
2857
2861
|
* this at two provide sites builds two instances, because layers are
|
|
2858
2862
|
* memoized by reference.
|
|
2859
2863
|
*/
|
|
2860
|
-
static readonly layerWith: (options: GitHubAppOptions) => Layer.Layer<GitHubApp>;
|
|
2864
|
+
static readonly layerWith: (options: GitHubAppOptions) => Layer.Layer<GitHubApp, never, Signature.Signature>;
|
|
2861
2865
|
/**
|
|
2862
2866
|
* A {@link GitHubClient} authenticated as an app installation.
|
|
2863
2867
|
*
|
|
@@ -2876,7 +2880,7 @@ export declare class GitHubApp extends GitHubApp_base {
|
|
|
2876
2880
|
* authorization failure, and widening every method's error channel to say so
|
|
2877
2881
|
* would tax every caller for a case only this layer can produce.
|
|
2878
2882
|
*/
|
|
2879
|
-
static readonly clientLayer: (request: TokenRequest, options?: GitHubAppOptions) => Layer.Layer<GitHubClient, GitHubAppError>;
|
|
2883
|
+
static readonly clientLayer: (request: TokenRequest, options?: GitHubAppOptions) => Layer.Layer<GitHubClient, GitHubAppError, Signature.Signature>;
|
|
2880
2884
|
/**
|
|
2881
2885
|
* A {@link GitHubClient} authenticated as the app itself, with an App JWT.
|
|
2882
2886
|
*
|
|
@@ -2929,7 +2933,7 @@ export declare class GitHubApp extends GitHubApp_base {
|
|
|
2929
2933
|
* Effect.runPromise(Effect.provide(sweep, layer));
|
|
2930
2934
|
* ```
|
|
2931
2935
|
*/
|
|
2932
|
-
static readonly appClientLayer: (credentials: AppCredentials, options?: GitHubAppOptions) => Layer.Layer<GitHubClient, GitHubAppError>;
|
|
2936
|
+
static readonly appClientLayer: (credentials: AppCredentials, options?: GitHubAppOptions) => Layer.Layer<GitHubClient, GitHubAppError, Signature.Signature>;
|
|
2933
2937
|
/**
|
|
2934
2938
|
* An installation token, reused from an {@link InstallationTokenStore}
|
|
2935
2939
|
* while it has `margin` (five minutes by default) left to live.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effected/github",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Typed GitHub REST and GraphQL services over the octokit core request surface, with app auth and resource helpers.",
|
|
6
6
|
"keywords": [
|
|
@@ -38,11 +38,11 @@
|
|
|
38
38
|
"./package.json": "./package.json"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@effected/crypto": "^0.
|
|
42
|
-
"@effected/github-references": "^0.
|
|
43
|
-
"@effected/jwt": "^0.
|
|
44
|
-
"@effected/oidc": "^0.
|
|
45
|
-
"@effected/semver": "^0.
|
|
41
|
+
"@effected/crypto": "^0.4.0",
|
|
42
|
+
"@effected/github-references": "^0.13.0",
|
|
43
|
+
"@effected/jwt": "^0.8.0",
|
|
44
|
+
"@effected/oidc": "^0.3.0",
|
|
45
|
+
"@effected/semver": "^0.20.0",
|
|
46
46
|
"@octokit/core": "^7.0.6",
|
|
47
47
|
"@octokit/plugin-paginate-rest": "^16.0.0",
|
|
48
48
|
"@octokit/types": "^18.0.0",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"tweetnacl": "1.0.3"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"effect": "
|
|
53
|
+
"effect": "~4.1.0"
|
|
54
54
|
},
|
|
55
55
|
"engines": {
|
|
56
56
|
"node": ">=24.11.0"
|