@usine/github 0.1.2 → 0.2.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.
Files changed (71) hide show
  1. package/README.md +31 -55
  2. package/dist/access.d.ts +30 -8
  3. package/dist/access.d.ts.map +1 -1
  4. package/dist/access.js +31 -8
  5. package/dist/access.js.map +1 -1
  6. package/dist/credentials.d.ts +6 -6
  7. package/dist/credentials.d.ts.map +1 -1
  8. package/dist/credentials.js +6 -6
  9. package/dist/credentials.js.map +1 -1
  10. package/dist/error.d.ts +28 -10
  11. package/dist/error.d.ts.map +1 -1
  12. package/dist/error.js +32 -7
  13. package/dist/error.js.map +1 -1
  14. package/dist/github-app.d.ts +12 -9
  15. package/dist/github-app.d.ts.map +1 -1
  16. package/dist/github-app.js +43 -29
  17. package/dist/github-app.js.map +1 -1
  18. package/dist/graphql.d.ts +11 -0
  19. package/dist/graphql.d.ts.map +1 -0
  20. package/dist/graphql.js +47 -0
  21. package/dist/graphql.js.map +1 -0
  22. package/dist/http.d.ts +9 -3
  23. package/dist/http.d.ts.map +1 -1
  24. package/dist/http.js +26 -8
  25. package/dist/http.js.map +1 -1
  26. package/dist/installation.d.ts +17 -9
  27. package/dist/installation.d.ts.map +1 -1
  28. package/dist/installation.js +17 -9
  29. package/dist/installation.js.map +1 -1
  30. package/dist/item-history.d.ts +57 -0
  31. package/dist/item-history.d.ts.map +1 -0
  32. package/dist/item-history.js +190 -0
  33. package/dist/item-history.js.map +1 -0
  34. package/dist/item-writer.d.ts +2 -2
  35. package/dist/item-writer.d.ts.map +1 -1
  36. package/dist/item-writer.js +1 -1
  37. package/dist/item-writer.js.map +1 -1
  38. package/dist/jwt.d.ts +3 -3
  39. package/dist/jwt.d.ts.map +1 -1
  40. package/dist/jwt.js +4 -4
  41. package/dist/jwt.js.map +1 -1
  42. package/dist/label-writer.d.ts +2 -2
  43. package/dist/label-writer.d.ts.map +1 -1
  44. package/dist/label-writer.js +2 -2
  45. package/dist/label-writer.js.map +1 -1
  46. package/dist/local-secrets.d.ts +2 -2
  47. package/dist/local-secrets.d.ts.map +1 -1
  48. package/dist/local-secrets.js +6 -6
  49. package/dist/local-secrets.js.map +1 -1
  50. package/dist/polling/content.js +2 -2
  51. package/dist/polling/detection.d.ts +9 -9
  52. package/dist/polling/detection.d.ts.map +1 -1
  53. package/dist/polling/detection.js +9 -9
  54. package/dist/polling/detection.js.map +1 -1
  55. package/dist/polling/labels.d.ts +5 -5
  56. package/dist/polling/labels.d.ts.map +1 -1
  57. package/dist/polling/labels.js +5 -5
  58. package/dist/polling/labels.js.map +1 -1
  59. package/dist/polling/payload.d.ts +10 -6
  60. package/dist/polling/payload.d.ts.map +1 -1
  61. package/dist/polling/payload.js +15 -11
  62. package/dist/polling/payload.js.map +1 -1
  63. package/dist/polling/polling.d.ts +18 -6
  64. package/dist/polling/polling.d.ts.map +1 -1
  65. package/dist/polling/polling.js +59 -52
  66. package/dist/polling/polling.js.map +1 -1
  67. package/dist/polling/queries.d.ts +6 -1
  68. package/dist/polling/queries.d.ts.map +1 -1
  69. package/dist/polling/queries.js +16 -0
  70. package/dist/polling/queries.js.map +1 -1
  71. package/package.json +8 -3
package/README.md CHANGED
@@ -1,41 +1,23 @@
1
1
  # @usine/github
2
2
 
3
- `@usine/github` gives an usine factory one GitHub App identity. It signs App JWTs, finds the App's installation, reports registry repositories that the installation does not cover, and mints two kinds of installation token:
3
+ Gives a usine factory one GitHub App identity. It signs App JWTs, finds the App's installation, reports registry repos that the installation doesn't cover, and mints two kinds of installation token:
4
4
 
5
5
  - an installation-wide token for orchestrator polling and writes;
6
- - a token restricted to one repository for a worker attempt.
6
+ - a token for one repo, for a worker attempt.
7
7
 
8
- Both token requests use a one-hour maximum lifetime. Expiry validation tolerates up to three minutes of clock skew while capping the local lease at one hour; expired tokens are rejected. Token values and the App private key stay inside Effect `Redacted` values.
8
+ Both tokens have a one-hour maximum lifetime. Expiry validation tolerates three minutes of clock skew and caps the local lease at one hour; expired tokens are rejected. Token values and the private key stay in Effect `Redacted` values.
9
9
 
10
- Import `GitHubApp`, credentials, access results, and typed App errors from `@usine/github/github-app`. `@usine/github/polling` provides `GitHubPolling` with its cursors, change-detection results, and payload snapshots. Item and label writes use `/item-writer` and `/label-writer`; local credential loading uses `/local-secrets`.
10
+ Import `GitHubApp`, credentials, access results, and typed App errors from `@usine/github/github-app`. `/polling` provides `GitHubPolling` with its cursors, change-detection results, and payload snapshots, plus `RepositoryLabel`, `RepositoryLabelCatalog`, and `RepositoryLabelsNotModified` for label catalogs and conditional responses. Item and label writes use `/item-writer` and `/label-writer`, the App's own changes on an item come from `/item-history`, and local credential loading uses `/local-secrets`.
11
11
 
12
- `/polling` also exports `RepositoryLabel`, `RepositoryLabelCatalog`, and
13
- `RepositoryLabelsNotModified` for reading label catalogs and handling conditional
14
- responses. These contracts share the same entry point as `GitHubPolling`.
12
+ The 0.x APIs can change between minor releases.
15
13
 
16
- ## Create the App manually
14
+ ## Set up the App
17
15
 
18
- Open your GitHub account or organization settings, select **Developer settings → GitHub Apps**, then select **New GitHub App**. Use a name that identifies the factory and set **Where can this GitHub App be installed?** to **Only on this account**. User authorization isn't required. You can turn off active webhooks for a polling-only development factory.
16
+ [Run a factory](https://docs.usine.dev/guides/) gives the steps under Connect a GitHub App: an App installable only on your account, without active webhooks, with Contents, Issues, and Pull requests read and write, Checks and Metadata read-only, and **No access** for everything else, including Workflows, Administration, and all organization and account permissions.
19
17
 
20
- Set these repository permissions:
18
+ GitHub grants Metadata read access automatically. Contents lets installation tokens use Git over HTTPS; with Workflows off, worker tokens can't edit `.github/workflows/`. User authorization isn't required. Install the App once, on the account that owns the managed repos, for every repo in `usine.yaml`; a factory expects one installation. GitHub's references are [Registering a GitHub App](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app) and [Choosing permissions for a GitHub App](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/choosing-permissions-for-a-github-app).
21
19
 
22
- | Permission | Access |
23
- | --- | --- |
24
- | Metadata | Read-only |
25
- | Contents | Read and write |
26
- | Issues | Read and write |
27
- | Pull requests | Read and write |
28
- | Checks | Read-only |
29
-
30
- Leave Workflows, Administration, every organization permission, and every account permission at **No access**. GitHub grants Metadata read access automatically. The Contents permission lets installation tokens authenticate Git over HTTPS; Workflows remains off, so worker tokens cannot edit files under `.github/workflows/`.
31
-
32
- Create the App, generate a private key, and note the numeric App ID. On the App's **Install App** page, install it on the account that owns the factory's managed repositories. Select every repository listed in `usine.yaml`. A factory expects one App installation, so don't install the same App on a second account.
33
-
34
- GitHub's current setup references are [Registering a GitHub App](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app) and [Choosing permissions for a GitHub App](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/choosing-permissions-for-a-github-app).
35
-
36
- ## Store the credentials
37
-
38
- The local runtime file is `<instance>/.usine/github-app.json`. Keep `.usine/` in the instance repo's `.gitignore`, and set the file mode to `0600`.
20
+ Store the App ID and private key in `<instance>/.usine/github-app.json` with mode `0600`, and keep `.usine/` in the instance repo's `.gitignore`:
39
21
 
40
22
  ```json
41
23
  {
@@ -44,20 +26,11 @@ The local runtime file is `<instance>/.usine/github-app.json`. Keep `.usine/` in
44
26
  }
45
27
  ```
46
28
 
47
- This command creates the JSON without copying PEM newlines by hand:
48
-
49
- ```sh
50
- mkdir -p .usine
51
- install -m 600 /dev/null .usine/github-app.json
52
- jq -n --argjson app_id "$APP_ID" --rawfile private_key factory.private-key.pem \
53
- '{app_id: $app_id, private_key: $private_key}' > .usine/github-app.json
54
- ```
55
-
56
- `USINE_GITHUB_APP_ID` and `USINE_GITHUB_PRIVATE_KEY` override their matching file fields. When both variables exist, the loader does not read the file.
29
+ `USINE_GITHUB_APP_ID` and `USINE_GITHUB_PRIVATE_KEY` override the matching fields. If both are set, the loader doesn't read the file.
57
30
 
58
31
  ## Compose the services
59
32
 
60
- The package root has no Node dependency. Supply an HTTP client plus platform file and path layers at the application edge:
33
+ The package root has no Node dependency. Supply an HTTP client and platform file and path layers at the edge:
61
34
 
62
35
  ```ts
63
36
  import { NodeFileSystem, NodePath } from "@effect/platform-node"
@@ -79,33 +52,38 @@ export const githubLayer = GitHubApp.layer.pipe(
79
52
  )
80
53
  ```
81
54
 
82
- `GitHubApp.layer` imports the private key once, when the layer is built: a key WebCrypto cannot import fails composition with `AppAuthenticationError` instead of failing the first request. Another credential source provides `GitHubCredentials` with an `AppCredentials` whose key went through the `RedactedPrivateKey` schema.
55
+ `GitHubApp.layer` imports the private key once, at build time, so a key that WebCrypto can't import fails composition with `AppAuthenticationError`, not the first request. Another credential source provides `GitHubCredentials` with `AppCredentials` whose key went through the `RedactedPrivateKey` schema.
83
56
 
84
- `installation()`, `installationToken()`, and `projectAccess()` share one lease: a single installation discovery and installation-wide mint, reused until five minutes before the token expires. Polling therefore costs no App requests between renewals. `workerToken()` mints on every call, so each attempt gets its own token.
57
+ `installation()`, `installationToken()`, and `projectAccess()` share one lease: one installation discovery and installation-wide mint, reused until five minutes before expiry, so polling makes no App requests between renewals. `workerToken()` mints on every call, so each attempt gets its own token.
85
58
 
86
- Call `GitHubApp.projectAccess(registry)` before scheduling work. Each result is either a `CoveredProject`, which carries the repository ID needed for scoped minting, or a `ProjectNotInstalledError`. A missing repository does not block covered projects.
59
+ Call `GitHubApp.projectAccess(registry)` before scheduling. Each result is a `CoveredProject`, with the repo ID for scoped minting, or a `ProjectNotInstalledError`. A missing repo doesn't block covered ones.
87
60
 
88
- Pass a `CoveredProject` to `GitHubApp.workerToken`. GitHub must confirm in the token response that the token covers exactly that repository ID; otherwise the call fails with `InvalidGitHubResponseError`.
61
+ Pass a `CoveredProject` and the attempt's loop permission level to `GitHubApp.workerToken`. If GitHub's response doesn't confirm that the token covers exactly that repo ID, it fails with `InvalidGitHubResponseError`. `WORKER_TOKEN_PERMISSIONS` lists each level's permissions: a `read` token has `contents: read`, so it can't push, and keeps `pull_requests: write` and `issues: write` for reviews and comments.
89
62
 
90
63
  ## Poll repository changes
91
64
 
92
- `GitHubPollingLayer` supplies the operations the orchestrator needs:
65
+ `GitHubPollingLayer` provides:
93
66
 
94
- - `changes(repository, cursor)` makes one conditional Issues REST request. It returns changed issue and pull-request numbers, the next ETag and watermark, plus any rate-limit delay GitHub requested.
95
- - `labels(repository)` reads every page of the repository label catalog for Board lane proposals.
67
+ - `changes(repository, cursor)`: one conditional Issues REST request, returning changed issue and pull request numbers, the next ETag and watermark, and any rate-limit delay.
68
+ - `labels(repository)`: every page of the repo's label catalog, for board lane proposals.
69
+ - `snapshot(repository, item)`: the issue or pull request payload through GraphQL, with its SHA-256 content hash. The stored payload keeps timestamps; the hash excludes timestamp fields at every level.
70
+ - `missingIssues(repository, numbers)`: the numbers the repo no longer has, deleted or transferred. It sends one GraphQL request per 50 numbers, with an aliased `issue(number:)` field each; an issue that returns null is missing.
96
71
 
97
- Change-detection results distinguish `nextPollAt`, the earliest next conditional poll, from `backoffUntil`, a request delay caused by `Retry-After` or rate-limit pressure. Self-write Hints can fetch an Item snapshot during the normal poll interval while respecting request backoff.
98
- - `snapshot(repository, item)` fetches the issue or pull-request payload through GraphQL and computes its SHA-256 content hash. The stored payload retains timestamps, while the hash excludes timestamp fields at every nesting level.
72
+ Change detection separates `nextPollAt`, the earliest next conditional poll, from `backoffUntil`, a delay from `Retry-After` or rate-limit pressure. Self-write hints can fetch a snapshot within the poll interval while respecting backoff.
99
73
 
100
- The REST cursor overlaps its watermark by five seconds. Repeated items are expected; the engine's permanent Event ledger owns deduplication. Provide `GitHubPollingLayer` with `GitHubApp`, an Effect HTTP client, and `Crypto.Crypto`. The package root remains platform-free.
74
+ The REST cursor overlaps its watermark by five seconds. Repeated items are expected; the engine's event ledger deduplicates. Provide `GitHubPollingLayer` with `GitHubApp`, an Effect HTTP client, and `Crypto.Crypto`.
101
75
 
102
- `GitHubItemWriter.updateLabels(repository, item, mutation)` adds destination lane labels and removes only explicitly lane-owned labels from an issue or pull request. It never replaces the complete applied-label set or deletes repository label definitions, so unrelated and concurrently added labels survive stale or truncated Item projections. The service requires `GitHubApp` and an Effect HTTP client.
76
+ `GitHubItemWriter.updateLabels(repository, item, mutation)` adds the destination lane's labels and removes only labels that lanes own. It never replaces an item's whole label set or deletes label definitions, so unrelated and concurrent labels survive stale or truncated projections.
103
77
 
104
- `GitHubLabelWriter.create(repository, label)` creates one repository label through `POST /repos/{owner}/{repo}/labels` using the installation-wide App token. Provide a name; color and description are optional. Reconciliation policy belongs to the orchestrator, so this service exposes creation only and never edits or deletes label definitions.
78
+ `GitHubItemHistory.appChanges(repository, item, since)` (`/item-history`) reads an issue or pull request timeline through GraphQL from `since`, and returns the factory App's own changes, oldest first: `LabelAdded`, `LabelRemoved`, `Commented`, and `Reviewed` (a submitted review with its state). Each change has GitHub's time; a label has its current name, color, and description, and comments and reviews have their URL. Other users and bots are left out. The App is matched by its slug, `Installation.appSlug` from `GitHubApp.installation()`, since GraphQL reports its writes with a `Bot` actor of that login. It reads up to ten pages of 100 items and fails with `InvalidGitHubResponseError` rather than return part of a longer timeline. An item the repo no longer has fails with `GitHubItemNotFoundError`.
105
79
 
106
- ## Real-App integration check
80
+ `GitHubLabelWriter.create(repository, label)` creates a label through `POST /repos/{owner}/{repo}/labels` with the installation-wide token. Color and description are optional. The orchestrator owns reconciliation, so this service only creates.
107
81
 
108
- Run the opt-in integration test against a disposable issue in a repository covered by the App:
82
+ The item writer, item history, and label writer each need `GitHubApp` and an Effect HTTP client.
83
+
84
+ ## Real-App integration test
85
+
86
+ Run the opt-in test against a disposable issue in a repo the App covers:
109
87
 
110
88
  ```sh
111
89
  export USINE_GITHUB_INTEGRATION_INSTANCE_DIRECTORY=/path/to/instance
@@ -115,6 +93,4 @@ export 'USINE_GITHUB_INTEGRATION_BOT_LOGIN=your-app-slug[bot]'
115
93
  pnpm --filter @usine/github test:integration
116
94
  ```
117
95
 
118
- The test mints both token shapes, posts one issue comment with the repository-scoped token, checks the comment author against the expected `<app>[bot]` login, and deletes the comment during cleanup. `@usine/orchestrator` has a separate live polling test that temporarily creates and applies a repository label.
119
-
120
- All APIs remain 0.x and can change between minor releases.
96
+ It mints both token kinds, posts an issue comment with the repo token, checks the author against `<app>[bot]`, and deletes the comment at cleanup. `@usine/orchestrator` has a separate live polling test that creates and applies a repo label.
package/dist/access.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { RepositoryName } from "@usine/core/repository";
2
2
  import { Schema } from "effect";
3
3
  import { RepositoryId, Installation } from "./installation.ts";
4
- /** Repository grants required for polling, label updates, and agent-authored changes. */
4
+ /** The repository permissions required for polling, label updates, and agent-authored changes. */
5
5
  export declare const REQUIRED_REPOSITORY_PERMISSIONS: {
6
6
  readonly checks: "read";
7
7
  readonly contents: "write";
@@ -10,38 +10,60 @@ export declare const REQUIRED_REPOSITORY_PERMISSIONS: {
10
10
  readonly pull_requests: "write";
11
11
  };
12
12
  export type RequiredRepositoryPermission = keyof typeof REQUIRED_REPOSITORY_PERMISSIONS;
13
- /** The required repository permissions an installation grant does not satisfy, as `name:level` strings. */
13
+ /**
14
+ * The repository permissions of an Attempt's token for each Loop permission level (ADR 0011).
15
+ * A `read` token can read code and post reviews and comments (`pull_requests` and `issues` are
16
+ * `write`), but can't push, merge, or update a branch, which need `contents: write`. Names and
17
+ * levels follow the installation token API:
18
+ * https://docs.github.com/en/rest/authentication/permissions-required-for-github-apps
19
+ */
20
+ export declare const WORKER_TOKEN_PERMISSIONS: {
21
+ readonly write: {
22
+ readonly checks: "read";
23
+ readonly contents: "write";
24
+ readonly issues: "write";
25
+ readonly metadata: "read";
26
+ readonly pull_requests: "write";
27
+ };
28
+ readonly read: {
29
+ readonly checks: "read";
30
+ readonly contents: "read";
31
+ readonly issues: "write";
32
+ readonly metadata: "read";
33
+ readonly pull_requests: "write";
34
+ };
35
+ };
36
+ /** Returns the required repository permissions that `granted` doesn't satisfy, as `name:level` strings. */
14
37
  export declare const missingPermissions: (granted: Readonly<Record<string, string>>) => ReadonlyArray<string>;
15
38
  declare const CoveredProject_base: Schema.Class<CoveredProject, Schema.TaggedStruct<"CoveredProject", {
16
39
  readonly installationId: Schema.brand<Schema.Int, "GitHubInstallationId">;
17
40
  readonly repository: Schema.brand<Schema.String, "RepositoryName">;
18
41
  readonly repositoryId: Schema.brand<Schema.Int, "GitHubRepositoryId">;
19
42
  }>, {}>;
20
- /** A registered repository covered by the discovered GitHub App installation. */
43
+ /** A registered repository covered by the GitHub App installation. */
21
44
  export declare class CoveredProject extends CoveredProject_base {
22
45
  }
23
46
  declare const ProjectNotInstalledError_base: Schema.Class<ProjectNotInstalledError, Schema.TaggedStruct<"ProjectNotInstalledError", {
24
47
  readonly repository: Schema.brand<Schema.String, "RepositoryName">;
25
48
  readonly message: Schema.NonEmptyString;
26
49
  }>, import("effect/Cause").YieldableError>;
27
- /** A registry repository the installation does not cover. Raised per project, so covered siblings still load. */
50
+ /** The error for a registry repository the installation doesn't cover. Reported per project, so covered projects still load. */
28
51
  export declare class ProjectNotInstalledError extends ProjectNotInstalledError_base {
29
52
  }
30
- /** The installation coverage result for one registered repository. */
53
+ /** The installation coverage of one registered repository. */
31
54
  export declare const ProjectAccess: Schema.Union<readonly [typeof CoveredProject, typeof ProjectNotInstalledError]>;
32
55
  export type ProjectAccess = typeof ProjectAccess.Type;
33
- /** A repository reported by GitHub for an installation, identified by its numeric id and full name. */
34
56
  export interface InstalledRepository {
35
57
  readonly id: RepositoryId;
36
58
  readonly name: RepositoryName;
37
59
  }
38
- /** Checks each registry repository against the installation's repositories and returns one `ProjectAccess` per project. */
60
+ /** Returns one `ProjectAccess` per registry repository by checking it against the installation's repositories. */
39
61
  export declare const deriveProjectAccess: (installation: Installation, registry: ReadonlyArray<RepositoryName>, installed: ReadonlyArray<InstalledRepository>) => ReadonlyArray<ProjectAccess>;
40
62
  declare const AppPermissionError_base: Schema.Class<AppPermissionError, Schema.TaggedStruct<"AppPermissionError", {
41
63
  readonly missing: Schema.$Array<Schema.NonEmptyString>;
42
64
  readonly message: Schema.NonEmptyString;
43
65
  }>, import("effect/Cause").YieldableError>;
44
- /** The installation lacks required repository grants; missing entries use name:level form. */
66
+ /** The error when the installation lacks required repository permissions; `missing` uses `name:level` form. */
45
67
  export declare class AppPermissionError extends AppPermissionError_base {
46
68
  }
47
69
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAkB,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE/E,yFAAyF;AACzF,eAAO,MAAM,+BAA+B;aAC1C,MAAM,EAAE,MAAM;aACd,QAAQ,EAAE,OAAO;aACjB,MAAM,EAAE,OAAO;aACf,QAAQ,EAAE,MAAM;aAChB,aAAa,EAAE,OAAO;CACd,CAAC;AAEX,MAAM,MAAM,4BAA4B,GAAG,MAAM,OAAO,+BAA+B,CAAC;AAKxF,2GAA2G;AAC3G,eAAO,MAAM,kBAAkB,YACpB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KACxC,aAAa,CAAC,MAAM,CAGpB,CAAC;;;;;;AAEJ,iFAAiF;AACjF,qBAAa,cAAe,SAAQ,mBAMlC;CAAG;;;;;AAEL,iHAAiH;AACjH,qBAAa,wBAAyB,SAAQ,6BAK5C;CAAG;AAEL,sEAAsE;AACtE,eAAO,MAAM,aAAa,iFAA2D,CAAC;AACtF,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAC;AAEtD,uGAAuG;AACvG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;CAC/B;AAED,2HAA2H;AAC3H,eAAO,MAAM,mBAAmB,iBAChB,YAAY,YAChB,aAAa,CAAC,cAAc,CAAC,aAC5B,aAAa,CAAC,mBAAmB,CAAC,KAC5C,aAAa,CAAC,aAAa,CAe7B,CAAC;;;;;AAEF,8FAA8F;AAC9F,qBAAa,kBAAmB,SAAQ,uBAKtC;CAAG"}
1
+ {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAkB,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE/E,kGAAkG;AAClG,eAAO,MAAM,+BAA+B;aAC1C,MAAM,EAAE,MAAM;aACd,QAAQ,EAAE,OAAO;aACjB,MAAM,EAAE,OAAO;aACf,QAAQ,EAAE,MAAM;aAChB,aAAa,EAAE,OAAO;CACd,CAAC;AAEX,MAAM,MAAM,4BAA4B,GAAG,MAAM,OAAO,+BAA+B,CAAC;AAExF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB;;iBAEjC,MAAM,EAAE,MAAM;iBACd,QAAQ,EAAE,OAAO;iBACjB,MAAM,EAAE,OAAO;iBACf,QAAQ,EAAE,MAAM;iBAChB,aAAa,EAAE,OAAO;;;iBAGtB,MAAM,EAAE,MAAM;iBACd,QAAQ,EAAE,MAAM;iBAChB,MAAM,EAAE,OAAO;iBACf,QAAQ,EAAE,MAAM;iBAChB,aAAa,EAAE,OAAO;;CAKzB,CAAC;AAKF,2GAA2G;AAC3G,eAAO,MAAM,kBAAkB,YACpB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KACxC,aAAa,CAAC,MAAM,CAGpB,CAAC;;;;;;AAEJ,sEAAsE;AACtE,qBAAa,cAAe,SAAQ,mBAMlC;CAAG;;;;;AAEL,gIAAgI;AAChI,qBAAa,wBAAyB,SAAQ,6BAK5C;CAAG;AAEL,8DAA8D;AAC9D,eAAO,MAAM,aAAa,iFAA2D,CAAC;AACtF,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAC;AAEtD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;CAC/B;AAED,kHAAkH;AAClH,eAAO,MAAM,mBAAmB,iBAChB,YAAY,YAChB,aAAa,CAAC,cAAc,CAAC,aAC5B,aAAa,CAAC,mBAAmB,CAAC,KAC5C,aAAa,CAAC,aAAa,CAe7B,CAAC;;;;;AAEF,+GAA+G;AAC/G,qBAAa,kBAAmB,SAAQ,uBAKtC;CAAG"}
package/dist/access.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { RepositoryName } from "@usine/core/repository";
2
2
  import { Schema } from "effect";
3
3
  import { InstallationId, RepositoryId, Installation } from "./installation.js";
4
- /** Repository grants required for polling, label updates, and agent-authored changes. */
4
+ /** The repository permissions required for polling, label updates, and agent-authored changes. */
5
5
  export const REQUIRED_REPOSITORY_PERMISSIONS = {
6
6
  checks: "read",
7
7
  contents: "write",
@@ -9,25 +9,48 @@ export const REQUIRED_REPOSITORY_PERMISSIONS = {
9
9
  metadata: "read",
10
10
  pull_requests: "write",
11
11
  };
12
+ /**
13
+ * The repository permissions of an Attempt's token for each Loop permission level (ADR 0011).
14
+ * A `read` token can read code and post reviews and comments (`pull_requests` and `issues` are
15
+ * `write`), but can't push, merge, or update a branch, which need `contents: write`. Names and
16
+ * levels follow the installation token API:
17
+ * https://docs.github.com/en/rest/authentication/permissions-required-for-github-apps
18
+ */
19
+ export const WORKER_TOKEN_PERMISSIONS = {
20
+ write: {
21
+ checks: "read",
22
+ contents: "write",
23
+ issues: "write",
24
+ metadata: "read",
25
+ pull_requests: "write",
26
+ },
27
+ read: {
28
+ checks: "read",
29
+ contents: "read",
30
+ issues: "write",
31
+ metadata: "read",
32
+ pull_requests: "write",
33
+ },
34
+ };
12
35
  const grants = (actual, required) => actual === required || (required === "read" && actual === "write");
13
- /** The required repository permissions an installation grant does not satisfy, as `name:level` strings. */
36
+ /** Returns the required repository permissions that `granted` doesn't satisfy, as `name:level` strings. */
14
37
  export const missingPermissions = (granted) => Object.entries(REQUIRED_REPOSITORY_PERMISSIONS).flatMap(([permission, required]) => grants(granted[permission], required) ? [] : [`${permission}:${required}`]);
15
- /** A registered repository covered by the discovered GitHub App installation. */
38
+ /** A registered repository covered by the GitHub App installation. */
16
39
  export class CoveredProject extends Schema.TaggedClass("@usine/github/ProjectAccess/CoveredProject")("CoveredProject", {
17
40
  installationId: InstallationId,
18
41
  repository: RepositoryName,
19
42
  repositoryId: RepositoryId,
20
43
  }) {
21
44
  }
22
- /** A registry repository the installation does not cover. Raised per project, so covered siblings still load. */
45
+ /** The error for a registry repository the installation doesn't cover. Reported per project, so covered projects still load. */
23
46
  export class ProjectNotInstalledError extends Schema.TaggedError("@usine/github/ProjectNotInstalledError")("ProjectNotInstalledError", {
24
47
  repository: RepositoryName,
25
48
  message: Schema.NonEmptyString,
26
49
  }) {
27
50
  }
28
- /** The installation coverage result for one registered repository. */
51
+ /** The installation coverage of one registered repository. */
29
52
  export const ProjectAccess = Schema.Union([CoveredProject, ProjectNotInstalledError]);
30
- /** Checks each registry repository against the installation's repositories and returns one `ProjectAccess` per project. */
53
+ /** Returns one `ProjectAccess` per registry repository by checking it against the installation's repositories. */
31
54
  export const deriveProjectAccess = (installation, registry, installed) => {
32
55
  const byName = new Map(installed.map((repo) => [repo.name.toLowerCase(), repo]));
33
56
  return registry.map((repository) => {
@@ -35,7 +58,7 @@ export const deriveProjectAccess = (installation, registry, installed) => {
35
58
  return match === undefined
36
59
  ? new ProjectNotInstalledError({
37
60
  repository,
38
- message: `The GitHub App installation does not cover ${repository}`,
61
+ message: `The GitHub App installation has no access to "${repository}"`,
39
62
  })
40
63
  : new CoveredProject({
41
64
  installationId: installation.id,
@@ -44,7 +67,7 @@ export const deriveProjectAccess = (installation, registry, installed) => {
44
67
  });
45
68
  });
46
69
  };
47
- /** The installation lacks required repository grants; missing entries use name:level form. */
70
+ /** The error when the installation lacks required repository permissions; `missing` uses `name:level` form. */
48
71
  export class AppPermissionError extends Schema.TaggedError("@usine/github/AppPermissionError")("AppPermissionError", {
49
72
  missing: Schema.Array(Schema.NonEmptyString).check(Schema.isNonEmpty()),
50
73
  message: Schema.NonEmptyString,
@@ -1 +1 @@
1
- {"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"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"}
@@ -1,27 +1,27 @@
1
1
  import { Context, Schema } from "effect";
2
- /** The numeric GitHub App identity included in signed App JWTs. */
2
+ /** The numeric GitHub App ID included in signed App JWTs. */
3
3
  export declare const AppId: Schema.brand<Schema.Int, "GitHubAppId">;
4
4
  export type AppId = typeof AppId.Type;
5
- /** A PEM-encoded RSA private key used to authenticate the GitHub App. */
5
+ /** A PEM-encoded RSA private key for the GitHub App. */
6
6
  export declare const PrivateKey: Schema.brand<Schema.NonEmptyString, "GitHubAppPrivateKey">;
7
7
  export type PrivateKey = typeof PrivateKey.Type;
8
- /** An App signing key that stays redacted in diagnostics and cannot be encoded. */
8
+ /** The App private key, redacted in diagnostics and not encodable. */
9
9
  export declare const RedactedPrivateKey: Schema.RedactedFromValue<Schema.brand<Schema.NonEmptyString, "GitHubAppPrivateKey">>;
10
10
  declare const AppCredentials_base: Schema.Class<AppCredentials, Schema.Struct<{
11
11
  readonly appId: Schema.brand<Schema.Int, "GitHubAppId">;
12
12
  readonly privateKey: Schema.RedactedFromValue<Schema.brand<Schema.NonEmptyString, "GitHubAppPrivateKey">>;
13
13
  }>, {}>;
14
- /** The App credentials the orchestrator keeps and never passes to a worker. */
14
+ /** The App credentials, kept by the orchestrator and never passed to a Worker. */
15
15
  export declare class AppCredentials extends AppCredentials_base {
16
16
  }
17
17
  declare const GitHubCredentials_base: Context.ServiceClass<GitHubCredentials, "@usine/github/GitHubCredentials", AppCredentials>;
18
- /** Supplies `AppCredentials`, so where credentials come from stays separate from how the App uses them. */
18
+ /** The service that provides `AppCredentials`. */
19
19
  export declare class GitHubCredentials extends GitHubCredentials_base {
20
20
  }
21
21
  declare const AppAuthenticationError_base: Schema.Class<AppAuthenticationError, Schema.TaggedStruct<"AppAuthenticationError", {
22
22
  readonly message: Schema.NonEmptyString;
23
23
  }>, import("effect/Cause").YieldableError>;
24
- /** The App private key cannot sign. Raised once, when the App layer is built. */
24
+ /** The error when the App private key can't sign, raised once when the App layer is built. */
25
25
  export declare class AppAuthenticationError extends AppAuthenticationError_base {
26
26
  }
27
27
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEzC,mEAAmE;AACnE,eAAO,MAAM,KAAK,yCAEjB,CAAC;AACF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAC;AAEtC,yEAAyE;AACzE,eAAO,MAAM,UAAU,4DAKoB,CAAC;AAC5C,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAC;AAEhD,mFAAmF;AACnF,eAAO,MAAM,kBAAkB,sFAAiE,CAAC;;;;;AAEjG,+EAA+E;AAC/E,qBAAa,cAAe,SAAQ,mBAGlC;CAAG;;AAEL,2GAA2G;AAC3G,qBAAa,iBAAkB,SAAQ,sBAEtC;CAAG;;;;AAEJ,iFAAiF;AACjF,qBAAa,sBAAuB,SAAQ,2BAI1C;CAAG"}
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEzC,6DAA6D;AAC7D,eAAO,MAAM,KAAK,yCAEjB,CAAC;AACF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAC;AAEtC,wDAAwD;AACxD,eAAO,MAAM,UAAU,4DAKoB,CAAC;AAC5C,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAC;AAEhD,sEAAsE;AACtE,eAAO,MAAM,kBAAkB,sFAAiE,CAAC;;;;;AAEjG,kFAAkF;AAClF,qBAAa,cAAe,SAAQ,mBAGlC;CAAG;;AAEL,kDAAkD;AAClD,qBAAa,iBAAkB,SAAQ,sBAEtC;CAAG;;;;AAEJ,8FAA8F;AAC9F,qBAAa,sBAAuB,SAAQ,2BAI1C;CAAG"}
@@ -1,20 +1,20 @@
1
1
  import { Context, Schema } from "effect";
2
- /** The numeric GitHub App identity included in signed App JWTs. */
2
+ /** The numeric GitHub App ID included in signed App JWTs. */
3
3
  export const AppId = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)).pipe(Schema.brand("GitHubAppId"));
4
- /** A PEM-encoded RSA private key used to authenticate the GitHub App. */
4
+ /** A PEM-encoded RSA private key for the GitHub App. */
5
5
  export const PrivateKey = Schema.NonEmptyString.check(Schema.isPattern(/^-----BEGIN (?:RSA )?PRIVATE KEY-----[\s\S]+-----END (?:RSA )?PRIVATE KEY-----\s*$/u, { message: "Expected a PEM-encoded RSA private key" })).pipe(Schema.brand("GitHubAppPrivateKey"));
6
- /** An App signing key that stays redacted in diagnostics and cannot be encoded. */
6
+ /** The App private key, redacted in diagnostics and not encodable. */
7
7
  export const RedactedPrivateKey = Schema.RedactedFromValue(PrivateKey, { disallowEncode: true });
8
- /** The App credentials the orchestrator keeps and never passes to a worker. */
8
+ /** The App credentials, kept by the orchestrator and never passed to a Worker. */
9
9
  export class AppCredentials extends Schema.Class("@usine/github/AppCredentials")({
10
10
  appId: AppId,
11
11
  privateKey: RedactedPrivateKey,
12
12
  }) {
13
13
  }
14
- /** Supplies `AppCredentials`, so where credentials come from stays separate from how the App uses them. */
14
+ /** The service that provides `AppCredentials`. */
15
15
  export class GitHubCredentials extends Context.Service()("@usine/github/GitHubCredentials") {
16
16
  }
17
- /** The App private key cannot sign. Raised once, when the App layer is built. */
17
+ /** The error when the App private key can't sign, raised once when the App layer is built. */
18
18
  export class AppAuthenticationError extends Schema.TaggedError("@usine/github/AppAuthenticationError")("AppAuthenticationError", {
19
19
  message: Schema.NonEmptyString,
20
20
  }) {
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEzC,mEAAmE;AACnE,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC1E,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAC5B,CAAC;AAGF,yEAAyE;AACzE,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CACnD,MAAM,CAAC,SAAS,CACd,qFAAqF,EACrF,EAAE,OAAO,EAAE,wCAAwC,EAAE,CACtD,CACF,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;AAG5C,mFAAmF;AACnF,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,iBAAiB,CAAC,UAAU,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;AAEjG,+EAA+E;AAC/E,MAAM,OAAO,cAAe,SAAQ,MAAM,CAAC,KAAK,CAAiB,8BAA8B,CAAC,CAAC;IAC/F,KAAK,EAAE,KAAK;IACZ,UAAU,EAAE,kBAAkB;CAC/B,CAAC;CAAG;AAEL,2GAA2G;AAC3G,MAAM,OAAO,iBAAkB,SAAQ,OAAO,CAAC,OAAO,EAAqC,CACzF,iCAAiC,CAClC;CAAG;AAEJ,iFAAiF;AACjF,MAAM,OAAO,sBAAuB,SAAQ,MAAM,CAAC,WAAW,CAC5D,sCAAsC,CACvC,CAAC,wBAAwB,EAAE;IAC1B,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC;CAAG"}
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEzC,6DAA6D;AAC7D,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC1E,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAC5B,CAAC;AAGF,wDAAwD;AACxD,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CACnD,MAAM,CAAC,SAAS,CACd,qFAAqF,EACrF,EAAE,OAAO,EAAE,wCAAwC,EAAE,CACtD,CACF,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;AAG5C,sEAAsE;AACtE,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,iBAAiB,CAAC,UAAU,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;AAEjG,kFAAkF;AAClF,MAAM,OAAO,cAAe,SAAQ,MAAM,CAAC,KAAK,CAAiB,8BAA8B,CAAC,CAAC;IAC/F,KAAK,EAAE,KAAK;IACZ,UAAU,EAAE,kBAAkB;CAC/B,CAAC;CAAG;AAEL,kDAAkD;AAClD,MAAM,OAAO,iBAAkB,SAAQ,OAAO,CAAC,OAAO,EAAqC,CACzF,iCAAiC,CAClC;CAAG;AAEJ,8FAA8F;AAC9F,MAAM,OAAO,sBAAuB,SAAQ,MAAM,CAAC,WAAW,CAC5D,sCAAsC,CACvC,CAAC,wBAAwB,EAAE;IAC1B,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC;CAAG"}
package/dist/error.d.ts CHANGED
@@ -1,36 +1,54 @@
1
1
  import { Schema } from "effect";
2
2
  import { InstallationDiscoveryError } from "./installation.ts";
3
3
  import { AppPermissionError } from "./access.ts";
4
- /** The GitHub request that failed, shared by API, rate-limit, and response errors. */
5
- export declare const GitHubOperation: Schema.Literals<readonly ["create-repository-label", "discover-installation", "fetch-item-labels", "fetch-issue-snapshot", "fetch-pull-request-snapshot", "list-installation-repositories", "list-repository-labels", "mint-installation-token", "mint-worker-token", "poll-repository-changes", "update-item-labels"]>;
4
+ /** The GitHub request that failed, used by API, rate-limit, and response errors. */
5
+ export declare const GitHubOperation: Schema.Literals<readonly ["create-repository-label", "discover-installation", "fetch-item-labels", "fetch-issue-snapshot", "fetch-item-timeline", "fetch-pull-request-snapshot", "find-missing-issues", "list-installation-repositories", "list-repository-labels", "mint-installation-token", "mint-worker-token", "poll-repository-changes", "update-item-labels"]>;
6
6
  export type GitHubOperation = typeof GitHubOperation.Type;
7
7
  declare const GitHubApiError_base: Schema.Class<GitHubApiError, Schema.TaggedStruct<"GitHubApiError", {
8
- readonly operation: Schema.Literals<readonly ["create-repository-label", "discover-installation", "fetch-item-labels", "fetch-issue-snapshot", "fetch-pull-request-snapshot", "list-installation-repositories", "list-repository-labels", "mint-installation-token", "mint-worker-token", "poll-repository-changes", "update-item-labels"]>;
8
+ readonly operation: Schema.Literals<readonly ["create-repository-label", "discover-installation", "fetch-item-labels", "fetch-issue-snapshot", "fetch-item-timeline", "fetch-pull-request-snapshot", "find-missing-issues", "list-installation-repositories", "list-repository-labels", "mint-installation-token", "mint-worker-token", "poll-repository-changes", "update-item-labels"]>;
9
9
  readonly status: Schema.Option<Schema.Int>;
10
10
  readonly message: Schema.NonEmptyString;
11
11
  }>, import("effect/Cause").YieldableError>;
12
- /** A failed GitHub request, with an HTTP status when a response was received. */
12
+ /** A failed GitHub request, with the HTTP status if a response was received. */
13
13
  export declare class GitHubApiError extends GitHubApiError_base {
14
14
  }
15
15
  declare const GitHubRateLimitError_base: Schema.Class<GitHubRateLimitError, Schema.TaggedStruct<"GitHubRateLimitError", {
16
- readonly operation: Schema.Literals<readonly ["create-repository-label", "discover-installation", "fetch-item-labels", "fetch-issue-snapshot", "fetch-pull-request-snapshot", "list-installation-repositories", "list-repository-labels", "mint-installation-token", "mint-worker-token", "poll-repository-changes", "update-item-labels"]>;
16
+ readonly operation: Schema.Literals<readonly ["create-repository-label", "discover-installation", "fetch-item-labels", "fetch-issue-snapshot", "fetch-item-timeline", "fetch-pull-request-snapshot", "find-missing-issues", "list-installation-repositories", "list-repository-labels", "mint-installation-token", "mint-worker-token", "poll-repository-changes", "update-item-labels"]>;
17
17
  readonly retryAt: Schema.DateTimeUtc;
18
18
  readonly message: Schema.NonEmptyString;
19
19
  }>, import("effect/Cause").YieldableError>;
20
- /** GitHub deferred the request until retryAt; callers can schedule a later attempt. */
20
+ /** The error when GitHub defers the request until `retryAt`. */
21
21
  export declare class GitHubRateLimitError extends GitHubRateLimitError_base {
22
22
  }
23
23
  declare const InvalidGitHubResponseError_base: Schema.Class<InvalidGitHubResponseError, Schema.TaggedStruct<"InvalidGitHubResponseError", {
24
- readonly operation: Schema.Literals<readonly ["create-repository-label", "discover-installation", "fetch-item-labels", "fetch-issue-snapshot", "fetch-pull-request-snapshot", "list-installation-repositories", "list-repository-labels", "mint-installation-token", "mint-worker-token", "poll-repository-changes", "update-item-labels"]>;
24
+ readonly operation: Schema.Literals<readonly ["create-repository-label", "discover-installation", "fetch-item-labels", "fetch-issue-snapshot", "fetch-item-timeline", "fetch-pull-request-snapshot", "find-missing-issues", "list-installation-repositories", "list-repository-labels", "mint-installation-token", "mint-worker-token", "poll-repository-changes", "update-item-labels"]>;
25
25
  readonly message: Schema.NonEmptyString;
26
- /** What made the response invalid: the decode path, the missing field, or the GraphQL errors. */
26
+ /** The decode path, missing field, or GraphQL errors. */
27
27
  readonly detail: Schema.NonEmptyString;
28
28
  }>, import("effect/Cause").YieldableError>;
29
- /** GitHub returned a response that cannot be decoded or is missing required content. */
29
+ /** The error when a GitHub response can't be decoded or lacks required content. */
30
30
  export declare class InvalidGitHubResponseError extends InvalidGitHubResponseError_base {
31
31
  }
32
- /** Failures from discovering installation access or making an authenticated GitHub request. */
32
+ declare const GitHubItemNotFoundError_base: Schema.Class<GitHubItemNotFoundError, Schema.TaggedStruct<"GitHubItemNotFoundError", {
33
+ readonly operation: Schema.Literals<readonly ["create-repository-label", "discover-installation", "fetch-item-labels", "fetch-issue-snapshot", "fetch-item-timeline", "fetch-pull-request-snapshot", "find-missing-issues", "list-installation-repositories", "list-repository-labels", "mint-installation-token", "mint-worker-token", "poll-repository-changes", "update-item-labels"]>;
34
+ readonly item: Schema.Int;
35
+ readonly message: Schema.NonEmptyString;
36
+ }>, import("effect/Cause").YieldableError>;
37
+ /**
38
+ * The error when the repository has no Item with this number because it was deleted,
39
+ * transferred, or is no longer readable by the App. The repository itself responded.
40
+ */
41
+ export declare class GitHubItemNotFoundError extends GitHubItemNotFoundError_base {
42
+ }
43
+ /** The errors from installation discovery or an authenticated GitHub request. */
33
44
  export declare const GitHubAppError: Schema.Union<readonly [typeof InstallationDiscoveryError, typeof AppPermissionError, typeof GitHubApiError, typeof GitHubRateLimitError, typeof InvalidGitHubResponseError]>;
34
45
  export type GitHubAppError = typeof GitHubAppError.Type;
46
+ /**
47
+ * Returns whether GitHub gave a definite response that a retry won't change: no usable
48
+ * installation, a missing permission, or a 4xx status other than 408 and 429 (for example, 422
49
+ * for an ungranted permission or 403 for a suspended installation). Send failures, server
50
+ * errors, rate limits, and responses that break GitHub's API contract aren't refusals.
51
+ */
52
+ export declare const isRefusal: (error: GitHubAppError) => boolean;
35
53
  export {};
36
54
  //# sourceMappingURL=error.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,sFAAsF;AACtF,eAAO,MAAM,eAAe,yTAY1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAC;;;;;;AAE1D,iFAAiF;AACjF,qBAAa,cAAe,SAAQ,mBAMlC;CAAG;;;;;;AAEL,uFAAuF;AACvF,qBAAa,oBAAqB,SAAQ,yBAMxC;CAAG;;;;IAQH,iGAAiG;;;AANnG,wFAAwF;AACxF,qBAAa,0BAA2B,SAAQ,+BAO9C;CAAG;AAEL,+FAA+F;AAC/F,eAAO,MAAM,cAAc,8KAMzB,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAC"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,oFAAoF;AACpF,eAAO,MAAM,eAAe,uWAc1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAC;;;;;;AAE1D,gFAAgF;AAChF,qBAAa,cAAe,SAAQ,mBAMlC;CAAG;;;;;;AAEL,gEAAgE;AAChE,qBAAa,oBAAqB,SAAQ,yBAMxC;CAAG;;;;IAQH,yDAAyD;;;AAN3D,mFAAmF;AACnF,qBAAa,0BAA2B,SAAQ,+BAO9C;CAAG;;;;;;AAEL;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,4BAM3C;CAAG;AAEL,iFAAiF;AACjF,eAAO,MAAM,cAAc,8KAMzB,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAC;AAExD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,UAAW,cAAc,KAAG,OAQ9C,CAAC"}
package/dist/error.js CHANGED
@@ -1,13 +1,15 @@
1
- import { Schema } from "effect";
1
+ import { Match, Option, Schema } from "effect";
2
2
  import { InstallationDiscoveryError } from "./installation.js";
3
3
  import { AppPermissionError } from "./access.js";
4
- /** The GitHub request that failed, shared by API, rate-limit, and response errors. */
4
+ /** The GitHub request that failed, used by API, rate-limit, and response errors. */
5
5
  export const GitHubOperation = Schema.Literals([
6
6
  "create-repository-label",
7
7
  "discover-installation",
8
8
  "fetch-item-labels",
9
9
  "fetch-issue-snapshot",
10
+ "fetch-item-timeline",
10
11
  "fetch-pull-request-snapshot",
12
+ "find-missing-issues",
11
13
  "list-installation-repositories",
12
14
  "list-repository-labels",
13
15
  "mint-installation-token",
@@ -15,29 +17,39 @@ export const GitHubOperation = Schema.Literals([
15
17
  "poll-repository-changes",
16
18
  "update-item-labels",
17
19
  ]);
18
- /** A failed GitHub request, with an HTTP status when a response was received. */
20
+ /** A failed GitHub request, with the HTTP status if a response was received. */
19
21
  export class GitHubApiError extends Schema.TaggedError("@usine/github/GitHubApiError")("GitHubApiError", {
20
22
  operation: GitHubOperation,
21
23
  status: Schema.Option(Schema.Int),
22
24
  message: Schema.NonEmptyString,
23
25
  }) {
24
26
  }
25
- /** GitHub deferred the request until retryAt; callers can schedule a later attempt. */
27
+ /** The error when GitHub defers the request until `retryAt`. */
26
28
  export class GitHubRateLimitError extends Schema.TaggedError("@usine/github/GitHubRateLimitError")("GitHubRateLimitError", {
27
29
  operation: GitHubOperation,
28
30
  retryAt: Schema.DateTimeUtc,
29
31
  message: Schema.NonEmptyString,
30
32
  }) {
31
33
  }
32
- /** GitHub returned a response that cannot be decoded or is missing required content. */
34
+ /** The error when a GitHub response can't be decoded or lacks required content. */
33
35
  export class InvalidGitHubResponseError extends Schema.TaggedError("@usine/github/InvalidGitHubResponseError")("InvalidGitHubResponseError", {
34
36
  operation: GitHubOperation,
35
37
  message: Schema.NonEmptyString,
36
- /** What made the response invalid: the decode path, the missing field, or the GraphQL errors. */
38
+ /** The decode path, missing field, or GraphQL errors. */
37
39
  detail: Schema.NonEmptyString,
38
40
  }) {
39
41
  }
40
- /** Failures from discovering installation access or making an authenticated GitHub request. */
42
+ /**
43
+ * The error when the repository has no Item with this number because it was deleted,
44
+ * transferred, or is no longer readable by the App. The repository itself responded.
45
+ */
46
+ export class GitHubItemNotFoundError extends Schema.TaggedError("@usine/github/GitHubItemNotFoundError")("GitHubItemNotFoundError", {
47
+ operation: GitHubOperation,
48
+ item: Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)),
49
+ message: Schema.NonEmptyString,
50
+ }) {
51
+ }
52
+ /** The errors from installation discovery or an authenticated GitHub request. */
41
53
  export const GitHubAppError = Schema.Union([
42
54
  InstallationDiscoveryError,
43
55
  AppPermissionError,
@@ -45,4 +57,17 @@ export const GitHubAppError = Schema.Union([
45
57
  GitHubRateLimitError,
46
58
  InvalidGitHubResponseError,
47
59
  ]);
60
+ /**
61
+ * Returns whether GitHub gave a definite response that a retry won't change: no usable
62
+ * installation, a missing permission, or a 4xx status other than 408 and 429 (for example, 422
63
+ * for an ungranted permission or 403 for a suspended installation). Send failures, server
64
+ * errors, rate limits, and responses that break GitHub's API contract aren't refusals.
65
+ */
66
+ export const isRefusal = (error) => Match.valueTags(error, {
67
+ InstallationDiscoveryError: () => true,
68
+ AppPermissionError: () => true,
69
+ GitHubApiError: ({ status }) => Option.exists(status, (code) => code >= 400 && code < 500 && code !== 408 && code !== 429),
70
+ GitHubRateLimitError: () => false,
71
+ InvalidGitHubResponseError: () => false,
72
+ });
48
73
  //# sourceMappingURL=error.js.map
package/dist/error.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,sFAAsF;AACtF,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC7C,yBAAyB;IACzB,uBAAuB;IACvB,mBAAmB;IACnB,sBAAsB;IACtB,6BAA6B;IAC7B,gCAAgC;IAChC,wBAAwB;IACxB,yBAAyB;IACzB,mBAAmB;IACnB,yBAAyB;IACzB,oBAAoB;CACrB,CAAC,CAAC;AAGH,iFAAiF;AACjF,MAAM,OAAO,cAAe,SAAQ,MAAM,CAAC,WAAW,CACpD,8BAA8B,CAC/B,CAAC,gBAAgB,EAAE;IAClB,SAAS,EAAE,eAAe;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC;CAAG;AAEL,uFAAuF;AACvF,MAAM,OAAO,oBAAqB,SAAQ,MAAM,CAAC,WAAW,CAC1D,oCAAoC,CACrC,CAAC,sBAAsB,EAAE;IACxB,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,MAAM,CAAC,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC;CAAG;AAEL,wFAAwF;AACxF,MAAM,OAAO,0BAA2B,SAAQ,MAAM,CAAC,WAAW,CAChE,0CAA0C,CAC3C,CAAC,4BAA4B,EAAE;IAC9B,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,MAAM,CAAC,cAAc;IAC9B,iGAAiG;IACjG,MAAM,EAAE,MAAM,CAAC,cAAc;CAC9B,CAAC;CAAG;AAEL,+FAA+F;AAC/F,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC;IACzC,0BAA0B;IAC1B,kBAAkB;IAClB,cAAc;IACd,oBAAoB;IACpB,0BAA0B;CAC3B,CAAC,CAAC"}
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,oFAAoF;AACpF,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC7C,yBAAyB;IACzB,uBAAuB;IACvB,mBAAmB;IACnB,sBAAsB;IACtB,qBAAqB;IACrB,6BAA6B;IAC7B,qBAAqB;IACrB,gCAAgC;IAChC,wBAAwB;IACxB,yBAAyB;IACzB,mBAAmB;IACnB,yBAAyB;IACzB,oBAAoB;CACrB,CAAC,CAAC;AAGH,gFAAgF;AAChF,MAAM,OAAO,cAAe,SAAQ,MAAM,CAAC,WAAW,CACpD,8BAA8B,CAC/B,CAAC,gBAAgB,EAAE;IAClB,SAAS,EAAE,eAAe;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC;CAAG;AAEL,gEAAgE;AAChE,MAAM,OAAO,oBAAqB,SAAQ,MAAM,CAAC,WAAW,CAC1D,oCAAoC,CACrC,CAAC,sBAAsB,EAAE;IACxB,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,MAAM,CAAC,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC;CAAG;AAEL,mFAAmF;AACnF,MAAM,OAAO,0BAA2B,SAAQ,MAAM,CAAC,WAAW,CAChE,0CAA0C,CAC3C,CAAC,4BAA4B,EAAE;IAC9B,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,MAAM,CAAC,cAAc;IAC9B,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC,cAAc;CAC9B,CAAC;CAAG;AAEL;;;GAGG;AACH,MAAM,OAAO,uBAAwB,SAAQ,MAAM,CAAC,WAAW,CAC7D,uCAAuC,CACxC,CAAC,yBAAyB,EAAE;IAC3B,SAAS,EAAE,eAAe;IAC1B,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC;CAAG;AAEL,iFAAiF;AACjF,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC;IACzC,0BAA0B;IAC1B,kBAAkB;IAClB,cAAc;IACd,oBAAoB;IACpB,0BAA0B;CAC3B,CAAC,CAAC;AAGH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAqB,EAAW,EAAE,CAC1D,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE;IACrB,0BAA0B,EAAE,GAAG,EAAE,CAAC,IAAI;IACtC,kBAAkB,EAAE,GAAG,EAAE,CAAC,IAAI;IAC9B,cAAc,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC;IAC5F,oBAAoB,EAAE,GAAG,EAAE,CAAC,KAAK;IACjC,0BAA0B,EAAE,GAAG,EAAE,CAAC,KAAK;CACxC,CAAC,CAAC"}