@happyvertical/repos 0.84.0 → 0.85.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/README.md CHANGED
@@ -47,6 +47,90 @@ const duplicates = await repo.searchIssues('kanban automation', {
47
47
  });
48
48
  ```
49
49
 
50
+ ## Forge integrations
51
+
52
+ The additive forge surface is provider-neutral at its boundary and keeps the
53
+ existing `IRepository` API compatible. Provider operations return both data and
54
+ request-scoped metadata, including provider request IDs and rate limits.
55
+
56
+ ### GitHub App installation authority
57
+
58
+ Create one `GitHubAppAuth` per request or background job. Do not retain it as a
59
+ process-global singleton. Installation tokens, in-flight token requests, expiry,
60
+ repository authorization, and revocation are isolated inside that instance.
61
+
62
+ ```typescript
63
+ import { GitHubAppAuth } from '@happyvertical/repos';
64
+
65
+ const auth = new GitHubAppAuth({
66
+ appId: process.env.GITHUB_APP_ID!,
67
+ privateKey: process.env.GITHUB_APP_PRIVATE_KEY!,
68
+ });
69
+
70
+ const installation = await auth.createInstallationContext({
71
+ installationId: '1234',
72
+ owner: 'happyvertical',
73
+ repo: 'sdk',
74
+ });
75
+
76
+ const pullRequest = await installation.forge.getPullRequest(1151);
77
+ const check = await installation.forge.createCheckRun({
78
+ name: 'Work authority',
79
+ headSha: pullRequest.data.headSha,
80
+ status: 'completed',
81
+ conclusion: 'success',
82
+ output: {
83
+ title: 'Authorized',
84
+ summary: 'The exact pull-request head satisfies current authority.',
85
+ },
86
+ });
87
+
88
+ console.log(check.metadata.requestId, check.metadata.rateLimit);
89
+ ```
90
+
91
+ `createInstallationContext()` fails closed when GitHub rejects the
92
+ installation, the token is invalid or expired, or the requested repository is
93
+ not accessible to the installation token. Call `revoke()` to revoke
94
+ every still-live token issued by this scoped authority and permanently close
95
+ the local context. Local authority closes even if GitHub is unavailable;
96
+ `revoke()` reports the remote failure and may be retried.
97
+
98
+ ### Signed webhooks
99
+
100
+ Give the verifier the exact bytes received from the HTTP server. Do not decode,
101
+ parse, normalize, or reserialize the body first. `verifyAndNormalize()` verifies
102
+ the HMAC-SHA256 signature with constant-time comparisons before decoding JSON.
103
+ The first secret is current; later entries permit bounded secret rotation.
104
+
105
+ ```typescript
106
+ import { GitHubWebhookVerifier } from '@happyvertical/repos';
107
+
108
+ const webhooks = new GitHubWebhookVerifier({
109
+ secrets: [process.env.GITHUB_WEBHOOK_SECRET!],
110
+ });
111
+
112
+ // rawBody must be the unchanged Uint8Array from the request.
113
+ const event = webhooks.verifyAndNormalize(rawBody, request.headers);
114
+
115
+ console.log(event.deliveryId, event.observation.kind, event.raw);
116
+ ```
117
+
118
+ Normalized observations cover installation/repository changes, pull requests,
119
+ reviews, pushes, commit statuses, check runs/suites, merge groups, merges,
120
+ deployments, and availability pings while preserving the parsed provider
121
+ payload in `raw`. Persist `deliveryId` under a unique constraint before applying
122
+ an observation. The exported `createGitHubWebhookFixture()` helper creates exact
123
+ deterministic bytes and signatures for duplicate, redelivery, delayed, and
124
+ out-of-order integration scenarios.
125
+
126
+ ### Errors and provider metadata
127
+
128
+ New forge APIs throw `ForgeError`, which exposes `code`, `provider`, `status`,
129
+ `requestId`, `rateLimit`, and `retryable`. Authentication and repository-scope
130
+ failures are not retryable. Network failures, transient provider failures, and
131
+ rate limits are identified explicitly; callers remain responsible for bounded
132
+ retry and durable delivery handling.
133
+
50
134
  ## Features
51
135
 
52
136
  - **Platform-agnostic**: Works with GitHub, GitLab, Bitbucket, Azure DevOps
@@ -99,6 +183,22 @@ const duplicates = await repo.searchIssues('kanban automation', {
99
183
  - `getIssueNodeId(issueNumber)` - Get GraphQL node ID for issue
100
184
  - `getPRNodeId(prNumber)` - Get GraphQL node ID for PR
101
185
 
186
+ ### Commit statuses and checks
187
+
188
+ The GitHub repository implementation also provides additive legacy-interface
189
+ extensions:
190
+
191
+ - `createCommitStatus(input)` and `listCommitStatuses(sha)`
192
+ - `createCheckRun(input)`, `updateCheckRun(id, input)`, and
193
+ `listCheckRuns(sha)`
194
+
195
+ These methods are optional on `IRepository`, preserving third-party adapter
196
+ implementations compiled against the existing contract. Prefer
197
+ `GitHubForgeProvider` for new provider-neutral integrations and response
198
+ metadata. Status and check reads collect every provider page, and check reads
199
+ include reruns (`filter=all`); forge response metadata reports the number of
200
+ pages and total results observed.
201
+
102
202
  ## Supported Platforms
103
203
 
104
204
  - ✅ **GitHub** - Full support