@effected/github 0.3.0 → 0.4.1

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/index.d.ts CHANGED
@@ -577,28 +577,92 @@ interface GitHubClientOptions {
577
577
  */
578
578
  readonly fetch?: typeof globalThis.fetch | undefined;
579
579
  }
580
+ /**
581
+ * One call served by {@link GitHubClient.layerFixture}, as recorded in
582
+ * {@link GitHubFixtures.requested}.
583
+ *
584
+ * @public
585
+ */
586
+ interface RecordedCall {
587
+ /** Which client surface was called. */
588
+ readonly kind: "request" | "requestDecoded" | "paginate" | "graphql";
589
+ /** The route literal, or the document name for `graphql`. */
590
+ readonly route: string;
591
+ /** The params (or GraphQL variables) the call was made with. */
592
+ readonly params: Record<string, unknown>;
593
+ /** The page size asked for; paginated reads only. */
594
+ readonly perPage?: number;
595
+ }
580
596
  /**
581
597
  * A recorded response table for {@link GitHubClient.layerFixture}.
582
598
  *
583
599
  * @public
584
600
  */
585
601
  interface GitHubFixtures {
586
- /** Keyed by route; the value is the `data` payload a request answers with. */
602
+ /**
603
+ * Keyed by route; the value is the `data` payload a request answers with.
604
+ *
605
+ * @remarks
606
+ * A recorded **`GitHubError` is the response**: the call fails with it. That
607
+ * is how a suite stubs a 404 (or a rate-limit, or a 422) deliberately,
608
+ * rather than relying on a route's absence to produce one — absence is a
609
+ * wiring mistake and {@link GitHubFixtures.unstubbed} treats it as such.
610
+ */
587
611
  readonly request?: Readonly<Record<string, unknown>> | undefined;
588
- /** Keyed by route; the value is the whole collection, paged on demand. */
589
- readonly paginate?: Readonly<Record<string, ReadonlyArray<unknown>>> | undefined;
612
+ /**
613
+ * Keyed by route; the value is the whole collection, paged on demand — or a
614
+ * `GitHubError` the paginated read fails with.
615
+ */
616
+ readonly paginate?: Readonly<Record<string, ReadonlyArray<unknown> | GitHubError>> | undefined;
590
617
  /** Keyed by document name; the value is the raw payload to decode. */
591
618
  readonly graphql?: Readonly<Record<string, unknown>> | undefined;
619
+ /**
620
+ * What a route with **no fixture entry** does. Defaults to `"die"`.
621
+ *
622
+ * @remarks
623
+ * A missing fixture is a **test wiring** mistake, not a condition the code
624
+ * under test should handle, so the default kills the fiber rather than
625
+ * entering the error channel — the same treatment an absent `graphql`
626
+ * fixture has always had.
627
+ *
628
+ * The default used to be `"fail"`, and the reason it changed is worth
629
+ * knowing before you set it back: **a typed failure is only loud in code
630
+ * that does not catch.** A consumer whose methods each catch `GitHubError`
631
+ * and report it — a per-resource sync, say — turns a missing stub into a
632
+ * *different execution path* rather than a failure, and the assertions then
633
+ * fail for a new reason with nothing in any message naming a fixture. That
634
+ * cost `@spencerbeggs/reposets` 28 tests reading as ordinary logic bugs.
635
+ *
636
+ * - `"die"` — defect naming the route. Loud in every consumer.
637
+ * - `"fail"` — the old behaviour: `GitHubError.notFound`. Rarely what you
638
+ * want now that a recorded `GitHubError` value stubs a failure explicitly:
639
+ * `{ "GET /repos/{owner}/{repo}": GitHubError.notFound("read", "repo") }`
640
+ * says which route fails and why, where absence says only "unwired".
641
+ * - `"empty"` — serve `{}` for a request and no items for a paginated read.
642
+ * For a suite whose subject is decisions rather than endpoints.
643
+ *
644
+ * `graphql` ignores this and always dies: its payload is decoded against the
645
+ * document's schema, so there is no empty value that would satisfy it.
646
+ */
647
+ readonly unstubbed?: "die" | "fail" | "empty" | undefined;
592
648
  /** What `rateLimit` answers. */
593
649
  readonly rateLimit?: RateLimitSnapshot | undefined;
594
650
  /**
595
- * Every route a paginated read requested, in order, with the page size asked
596
- * for. Populated by the fixture as the test runs.
597
- */
598
- readonly requested?: Array<{
599
- readonly route: string;
600
- readonly perPage: number;
601
- }> | undefined;
651
+ * Every call the fixture served, in order. Populated as the test runs.
652
+ *
653
+ * @remarks
654
+ * `kind` says which surface was used. A paginated read carries the
655
+ * `perPage` it asked for; `request` and `requestDecoded` carry the
656
+ * **params** they were called with, which is what lets a suite assert that a
657
+ * method sent the right `owner`/`repo`/body rather than only the right
658
+ * route. `graphql` records the document name as `route`.
659
+ *
660
+ * Recording params was added for the resource modules ported in from
661
+ * `@spencerbeggs/reposets`, whose ~80-line hand-rolled harness existed
662
+ * because every one of their methods goes through `request` and a fixture
663
+ * could assert nothing about them.
664
+ */
665
+ readonly requested?: Array<RecordedCall> | undefined;
602
666
  }
603
667
  declare const GitHubClient_base: Context.ServiceClass<GitHubClient, "@effected/github/GitHubClient", GitHubClientShape>;
604
668
  /**
@@ -1062,6 +1126,149 @@ declare class CheckRun extends CheckRun_base {
1062
1126
  static readonly layerTest: (overrides?: Partial<CheckRunShape>) => Layer.Layer<CheckRun>;
1063
1127
  }
1064
1128
  //#endregion
1129
+ //#region src/CodeScanning.d.ts
1130
+ /**
1131
+ * A CodeQL default-setup configuration.
1132
+ *
1133
+ * @remarks
1134
+ * Every field is optional and an **omitted field means "leave it alone"**, which
1135
+ * is why this is a partial rather than a full configuration: sending
1136
+ * `undefined` for a key the caller never mentioned would clear a setting they
1137
+ * did not ask to change.
1138
+ *
1139
+ * @public
1140
+ */
1141
+ interface CodeScanningSetup {
1142
+ /** Whether default setup is `configured` or `not-configured`. */
1143
+ readonly state?: "configured" | "not-configured" | undefined;
1144
+ /** The CodeQL languages to analyse. */
1145
+ readonly languages?: ReadonlyArray<string> | undefined;
1146
+ /** `default` or `extended`. */
1147
+ readonly query_suite?: string | undefined;
1148
+ /** `remote` or `remote_and_local`. */
1149
+ readonly threat_model?: string | undefined;
1150
+ /** `standard` or `labeled`. */
1151
+ readonly runner_type?: string | undefined;
1152
+ /** The runner label, when `runner_type` is `labeled`. */
1153
+ readonly runner_label?: string | undefined;
1154
+ }
1155
+ /**
1156
+ * CodeQL default setup, and the language detection that gates it.
1157
+ *
1158
+ * @public
1159
+ */
1160
+ interface CodeScanningShape {
1161
+ /**
1162
+ * Apply a default-setup configuration.
1163
+ *
1164
+ * @remarks
1165
+ * The endpoint answers **202 Accepted** and configures asynchronously.
1166
+ * Nothing here polls: a successful call means GitHub accepted the request,
1167
+ * not that scanning is running.
1168
+ *
1169
+ * **Turning it back off does not undo everything it did.** Setting `state`
1170
+ * to `not-configured` stops default setup, but the synthetic CodeQL workflow
1171
+ * GitHub created when it was enabled **survives** — it remains listed among
1172
+ * the repository's workflows afterwards. A caller that treats "default setup
1173
+ * is off" as "no CodeQL workflow exists" will be wrong, and one that counts
1174
+ * workflows to decide whether a repository has any CI will count that one.
1175
+ * Reported by `@spencerbeggs/reposets` (dogfood round 8, 2026-08-14) from a
1176
+ * real organization, not inferred from the API description.
1177
+ */
1178
+ readonly configure: (setup: CodeScanningSetup) => Effect.Effect<void, GitHubError, Repo>;
1179
+ /**
1180
+ * The languages GitHub detects in the repository.
1181
+ *
1182
+ * @remarks
1183
+ * The response maps language name to bytes; only the names are returned, in
1184
+ * GitHub's own order (most bytes first). Use it to filter a configured
1185
+ * language list down to what the repository actually contains — GitHub
1186
+ * rejects a default-setup call naming a language it does not detect.
1187
+ */
1188
+ readonly languages: () => Effect.Effect<ReadonlyArray<string>, GitHubError, Repo>;
1189
+ }
1190
+ declare const CodeScanning_base: Context.ServiceClass<CodeScanning, "@effected/github/CodeScanning", CodeScanningShape>;
1191
+ /**
1192
+ * CodeQL default setup.
1193
+ *
1194
+ * @public
1195
+ */
1196
+ declare class CodeScanning extends CodeScanning_base {
1197
+ /**
1198
+ * @remarks
1199
+ * The callback is written `(client) => make(client)` rather than passed as
1200
+ * `make` directly, and that is load-bearing: a static initializer runs while
1201
+ * the module body is still evaluating, so naming a `const` declared further
1202
+ * down throws `Cannot access 'make' before initialization` **at import time**,
1203
+ * with a clean typecheck.
1204
+ */
1205
+ static readonly layer: Layer.Layer<CodeScanning, never, GitHubClient>;
1206
+ /** An in-memory double; unstubbed members die naming themselves. */
1207
+ static readonly makeTest: (overrides?: Partial<CodeScanningShape>) => CodeScanningShape;
1208
+ /** {@link CodeScanning.makeTest} behind a `Layer`. */
1209
+ static readonly layerTest: (overrides?: Partial<CodeScanningShape>) => Layer.Layer<CodeScanning>;
1210
+ }
1211
+ //#endregion
1212
+ //#region src/DeploymentEnvironment.d.ts
1213
+ /**
1214
+ * A deployment environment, as listing returns it.
1215
+ *
1216
+ * @public
1217
+ */
1218
+ interface DeploymentEnvironmentInfo {
1219
+ readonly name: string;
1220
+ }
1221
+ /**
1222
+ * Deployment environments.
1223
+ *
1224
+ * @public
1225
+ */
1226
+ interface DeploymentEnvironmentShape {
1227
+ /**
1228
+ * Create or update a deployment environment.
1229
+ *
1230
+ * @remarks
1231
+ * The route is **idempotent** — a `PUT` on an existing environment updates it
1232
+ * — so there is no list-then-branch here, unlike variables.
1233
+ *
1234
+ * `config` stays an open record because the protection-rule body is a moving
1235
+ * target: wait timers, reviewers, deployment-branch policies and whatever
1236
+ * GitHub adds next.
1237
+ */
1238
+ readonly upsert: (name: string, config?: Record<string, unknown>) => Effect.Effect<void, GitHubError, Repo>;
1239
+ /** The repository's deployment environments. */
1240
+ readonly list: () => Effect.Effect<ReadonlyArray<DeploymentEnvironmentInfo>, GitHubError, Repo>;
1241
+ /**
1242
+ * Remove one deployment environment.
1243
+ *
1244
+ * @remarks
1245
+ * **This deletes the environment's secrets and variables with it.** Anything
1246
+ * sequencing a cleanup pass depends on that: removing an environment after
1247
+ * its secrets is redundant, and removing it before them makes those deletions
1248
+ * fail against a resource that no longer exists.
1249
+ */
1250
+ readonly delete: (name: string) => Effect.Effect<void, GitHubError, Repo>;
1251
+ }
1252
+ declare const DeploymentEnvironment_base: Context.ServiceClass<DeploymentEnvironment, "@effected/github/DeploymentEnvironment", DeploymentEnvironmentShape>;
1253
+ /**
1254
+ * Deployment environments.
1255
+ *
1256
+ * @public
1257
+ */
1258
+ declare class DeploymentEnvironment extends DeploymentEnvironment_base {
1259
+ /**
1260
+ * @remarks
1261
+ * `(client) => make(client)` rather than `make`: a static initializer runs
1262
+ * while the module body is still evaluating, so naming a `const` declared
1263
+ * further down throws at import time with a clean typecheck.
1264
+ */
1265
+ static readonly layer: Layer.Layer<DeploymentEnvironment, never, GitHubClient>;
1266
+ /** An in-memory double; unstubbed members die naming themselves. */
1267
+ static readonly makeTest: (overrides?: Partial<DeploymentEnvironmentShape>) => DeploymentEnvironmentShape;
1268
+ /** {@link DeploymentEnvironment.makeTest} behind a `Layer`. */
1269
+ static readonly layerTest: (overrides?: Partial<DeploymentEnvironmentShape>) => Layer.Layer<DeploymentEnvironment>;
1270
+ }
1271
+ //#endregion
1065
1272
  //#region src/GitBranch.d.ts
1066
1273
  /**
1067
1274
  * What {@link GitBranchShape.upsert} did.
@@ -1938,6 +2145,79 @@ type RepositorySettings = Data<"GET /repos/{owner}/{repo}">;
1938
2145
  * @public
1939
2146
  */
1940
2147
  type RepositoryPatch = Omit<Params<"PATCH /repos/{owner}/{repo}">, "owner" | "repo">;
2148
+ /**
2149
+ * Whether an account is a user or an organization.
2150
+ *
2151
+ * @public
2152
+ */
2153
+ type OwnerType = "User" | "Organization";
2154
+ /**
2155
+ * Fields in the user-facing `security_and_analysis` block that GitHub accepts
2156
+ * as `{ status: "enabled" | "disabled" }`.
2157
+ *
2158
+ * @remarks
2159
+ * A caller supplies the bare string; it is wrapped before sending.
2160
+ *
2161
+ * @public
2162
+ */
2163
+ declare const SECURITY_ANALYSIS_STATUS_FIELDS: ReadonlySet<string>;
2164
+ /**
2165
+ * Settings reachable **only** through the GraphQL `updateRepository` mutation,
2166
+ * mapped from snake_case keys to camelCase GraphQL input fields.
2167
+ *
2168
+ * @remarks
2169
+ * GitHub never exposed these two on the REST repository endpoint. Setting
2170
+ * either forces a second round trip to learn the repository's node id.
2171
+ *
2172
+ * @public
2173
+ */
2174
+ declare const GRAPHQL_ONLY_SETTINGS: Readonly<Record<string, string>>;
2175
+ /**
2176
+ * Translate a user-facing `security_and_analysis` block into the shape
2177
+ * `PATCH /repos/{owner}/{repo}` expects.
2178
+ *
2179
+ * @remarks
2180
+ * **Both shapes are accepted.** A bare `"enabled"` / `"disabled"` is wrapped;
2181
+ * an already-wrapped `{ status }` — which is what `RepositoryPatch` actually
2182
+ * types, since it is GitHub's own parameter type — passes through untouched.
2183
+ * Accepting only the bare string would silently drop the block for a caller
2184
+ * following the types.
2185
+ *
2186
+ * Reviewer entries must already carry a numeric `reviewer_id` and
2187
+ * `reviewer_type`; resolving those from team slugs is the caller's job — see
2188
+ * `Ruleset.teamId`.
2189
+ *
2190
+ * An **empty** `delegated_bypass_reviewers` array is treated as "no change"
2191
+ * rather than "no reviewers". GitHub rejects `{ reviewers: [] }` outright when
2192
+ * delegated bypass is enabled, so forwarding it would turn an omission into a
2193
+ * failure.
2194
+ *
2195
+ * @public
2196
+ */
2197
+ declare const transformSecurityAndAnalysis: (value: unknown) => Record<string, unknown> | undefined;
2198
+ /**
2199
+ * What {@link GitHubRepositoryShape.applySettings} actually sent.
2200
+ *
2201
+ * @remarks
2202
+ * **These are the fields that went out, not the fields you asked for**, and the
2203
+ * difference is the point. `applySettings` drops what GitHub would reject —
2204
+ * merge keys whose strategy is being disabled, a `security_and_analysis` block
2205
+ * that normalises to nothing — so a caller reporting `Object.keys(input)` is
2206
+ * describing its own intent while the package decides the content. The two
2207
+ * agree right up until a field is dropped, which is exactly the case anyone
2208
+ * reading a dry run is trying to check.
2209
+ *
2210
+ * Both lists use the **caller's** key names, not the wire names, because the
2211
+ * audience for them is a person reading a plan against the config they wrote.
2212
+ *
2213
+ * @public
2214
+ */
2215
+ interface AppliedSettings {
2216
+ /** Keys sent on the REST patch, after preparation dropped anything GitHub would refuse. */
2217
+ readonly rest: ReadonlyArray<string>;
2218
+ /** Keys sent through the GraphQL mutation, named as the caller supplied them. */
2219
+ readonly graphql: ReadonlyArray<string>;
2220
+ }
1941
2221
  /**
1942
2222
  * The repository itself.
1943
2223
  *
@@ -1964,6 +2244,41 @@ interface GitHubRepositoryShape {
1964
2244
  * mutations, which is why a second consumer cast `repos.get` for it alone.
1965
2245
  */
1966
2246
  readonly nodeId: Effect.Effect<string, GitHubError, Repo>;
2247
+ /**
2248
+ * Whether the repository's owner is a user or an organization.
2249
+ *
2250
+ * @remarks
2251
+ * Gates the settings that only exist on organization-owned repositories:
2252
+ * sending one to a personal repository is rejected, so a caller applying a
2253
+ * shared settings template filters by this first.
2254
+ *
2255
+ * The route is account-scoped (`GET /users/{username}`) but the question is a
2256
+ * repository question — *may I send org-only fields to this repository?* —
2257
+ * so it sources the login from `Repo.owner` rather than taking an argument.
2258
+ * Shaping the API around the route instead of the question would hand every
2259
+ * caller a login to thread for no reason.
2260
+ */
2261
+ readonly ownerType: Effect.Effect<OwnerType, GitHubError, Repo>;
2262
+ /**
2263
+ * Apply a settings map that may span REST and GraphQL.
2264
+ *
2265
+ * @remarks
2266
+ * `updateSettings` is the thin, faithfully-typed PATCH and returns what
2267
+ * GitHub then reports. This is the **applicator**: it takes an open map,
2268
+ * routes each key to whichever API can actually set it, and returns nothing.
2269
+ *
2270
+ * Two settings — `has_sponsorships` and `has_pull_requests` — have never
2271
+ * existed on the REST endpoint and are only reachable through GraphQL's
2272
+ * `updateRepository`, which addresses a repository by **node id**. So a map
2273
+ * touching either costs an extra read; a map touching neither does not, which
2274
+ * is the common case.
2275
+ *
2276
+ * The map is open by design. GitHub's settings surface is large and moving,
2277
+ * and a closed type here would date the package — but it also means a typo is
2278
+ * forwarded rather than rejected, so a caller that owns a schema should
2279
+ * validate before calling.
2280
+ */
2281
+ readonly applySettings: (settings: Record<string, unknown>) => Effect.Effect<AppliedSettings, GitHubError | GitHubGraphQLError, Repo>;
1967
2282
  }
1968
2283
  declare const GitHubRepository_base: Context.ServiceClass<GitHubRepository, "@effected/github/GitHubRepository", GitHubRepositoryShape>;
1969
2284
  /**
@@ -2345,6 +2660,335 @@ declare class PullRequestComment extends PullRequestComment_base {
2345
2660
  static readonly layerTest: (overrides?: Partial<PullRequestCommentShape>) => Layer.Layer<PullRequestComment>;
2346
2661
  }
2347
2662
  //#endregion
2663
+ //#region src/RepositorySecret.d.ts
2664
+ /**
2665
+ * Which secret store an operation acts on.
2666
+ *
2667
+ * @remarks
2668
+ * Three separate stores on the same repository, each with **its own public
2669
+ * key** — which is why a key fetch cannot be cached across scopes.
2670
+ *
2671
+ * @public
2672
+ */
2673
+ type SecretScope = "actions" | "dependabot" | "codespaces";
2674
+ /**
2675
+ * A secret, as listing returns it.
2676
+ *
2677
+ * @remarks
2678
+ * The name only. GitHub never returns a secret's value from any endpoint —
2679
+ * that is the point of a secret store — so there is nothing else to carry, and
2680
+ * a consumer comparing desired against live can detect a **deleted** secret but
2681
+ * never an **edited** one.
2682
+ *
2683
+ * @public
2684
+ */
2685
+ interface SecretInfo {
2686
+ readonly name: string;
2687
+ }
2688
+ /**
2689
+ * Repository and environment secrets.
2690
+ *
2691
+ * @public
2692
+ */
2693
+ interface RepositorySecretShape {
2694
+ /** Encrypt and write one repository secret in the given store. */
2695
+ readonly set: (name: string, value: Redacted.Redacted<string>, scope?: SecretScope) => Effect.Effect<void, GitHubError, Repo>;
2696
+ /** The names of the repository's secrets in the given store. */
2697
+ readonly list: (scope?: SecretScope) => Effect.Effect<ReadonlyArray<SecretInfo>, GitHubError, Repo>;
2698
+ /** Remove one repository secret from the given store. */
2699
+ readonly delete: (name: string, scope?: SecretScope) => Effect.Effect<void, GitHubError, Repo>;
2700
+ /** Encrypt and write one environment secret. */
2701
+ readonly setForEnvironment: (environment: string, name: string, value: Redacted.Redacted<string>) => Effect.Effect<void, GitHubError, Repo>;
2702
+ /** The names of one environment's secrets. */
2703
+ readonly listForEnvironment: (environment: string) => Effect.Effect<ReadonlyArray<SecretInfo>, GitHubError, Repo>;
2704
+ /** Remove one environment secret. */
2705
+ readonly deleteForEnvironment: (environment: string, name: string) => Effect.Effect<void, GitHubError, Repo>;
2706
+ }
2707
+ declare const RepositorySecret_base: Context.ServiceClass<RepositorySecret, "@effected/github/RepositorySecret", RepositorySecretShape>;
2708
+ /**
2709
+ * Secrets, encrypted client-side before they leave the process.
2710
+ *
2711
+ * @remarks
2712
+ * Every write is a **two-step**: fetch the store's public key, then `PUT` a
2713
+ * libsodium sealed box. The plaintext never crosses the wire, and the key fetch
2714
+ * cannot be cached across stores because each has its own key.
2715
+ *
2716
+ * ## The value is `Redacted`
2717
+ *
2718
+ * Not decoration. A plaintext secret in a `string` is one interpolation, one
2719
+ * `JSON.stringify` of a params object, or one logged error away from a
2720
+ * transcript — and the log line that leaks it usually looks like a diagnostic
2721
+ * someone added to debug an unrelated failure. `Redacted` closes those paths at
2722
+ * the type; this module performs the single `Redacted.value` unwrap, at the
2723
+ * moment of encryption, and the sealed box is what continues.
2724
+ *
2725
+ * @public
2726
+ */
2727
+ declare class RepositorySecret extends RepositorySecret_base {
2728
+ /**
2729
+ * @remarks
2730
+ * `(client) => make(client)` rather than `make`: a static initializer runs
2731
+ * while the module body is still evaluating, so naming a `const` declared
2732
+ * further down throws at import time with a clean typecheck.
2733
+ */
2734
+ static readonly layer: Layer.Layer<RepositorySecret, never, GitHubClient>;
2735
+ /** An in-memory double; unstubbed members die naming themselves. */
2736
+ static readonly makeTest: (overrides?: Partial<RepositorySecretShape>) => RepositorySecretShape;
2737
+ /** {@link RepositorySecret.makeTest} behind a `Layer`. */
2738
+ static readonly layerTest: (overrides?: Partial<RepositorySecretShape>) => Layer.Layer<RepositorySecret>;
2739
+ }
2740
+ //#endregion
2741
+ //#region src/RepositorySecurity.d.ts
2742
+ /**
2743
+ * The three repository security features that have their own endpoints.
2744
+ *
2745
+ * @public
2746
+ */
2747
+ interface RepositorySecurityShape {
2748
+ /** Whether Dependabot vulnerability alerts are on. */
2749
+ readonly vulnerabilityAlerts: () => Effect.Effect<boolean, GitHubError, Repo>;
2750
+ /** Turn Dependabot vulnerability alerts on or off. */
2751
+ readonly setVulnerabilityAlerts: (enabled: boolean) => Effect.Effect<void, GitHubError, Repo>;
2752
+ /** Whether Dependabot security pull requests are on. */
2753
+ readonly automatedSecurityFixes: () => Effect.Effect<boolean, GitHubError, Repo>;
2754
+ /** Turn Dependabot security pull requests on or off. */
2755
+ readonly setAutomatedSecurityFixes: (enabled: boolean) => Effect.Effect<void, GitHubError, Repo>;
2756
+ /** Whether the private vulnerability reporting inbox is on. */
2757
+ readonly privateVulnerabilityReporting: () => Effect.Effect<boolean, GitHubError, Repo>;
2758
+ /** Turn the private vulnerability reporting inbox on or off. */
2759
+ readonly setPrivateVulnerabilityReporting: (enabled: boolean) => Effect.Effect<void, GitHubError, Repo>;
2760
+ }
2761
+ declare const RepositorySecurity_base: Context.ServiceClass<RepositorySecurity, "@effected/github/RepositorySecurity", RepositorySecurityShape>;
2762
+ /**
2763
+ * Repository security features with dedicated endpoints.
2764
+ *
2765
+ * @remarks
2766
+ * These are **not** `security_and_analysis` fields and cannot ride along on the
2767
+ * settings `PATCH`. Each is its own pair of endpoints where **the HTTP verb is
2768
+ * the value**, which is why every setter branches on `enabled` rather than
2769
+ * sending a body.
2770
+ *
2771
+ * ## Reading them is inconsistent, and the inconsistency is GitHub's
2772
+ *
2773
+ * Preserved faithfully rather than smoothed over, because smoothing it would
2774
+ * mean inventing a behaviour for one of the three:
2775
+ *
2776
+ * | Feature | Enabled | Disabled |
2777
+ * | :--- | :--- | :--- |
2778
+ * | `vulnerability-alerts` | `204` | **`404`** |
2779
+ * | `automated-security-fixes` | `200 { enabled: true }` | `200 { enabled: false }` |
2780
+ * | `private-vulnerability-reporting` | `200 { enabled: true }` | `200 { enabled: false }` |
2781
+ *
2782
+ * So `vulnerabilityAlerts` maps `notFound` to `false` — and **only** `notFound`;
2783
+ * every other failure still fails. A 404 from the other two is a real failure
2784
+ * and stays one, which is why the mapping is not applied uniformly.
2785
+ *
2786
+ * @public
2787
+ */
2788
+ declare class RepositorySecurity extends RepositorySecurity_base {
2789
+ /**
2790
+ * @remarks
2791
+ * `(client) => make(client)` rather than `make`: a static initializer runs
2792
+ * while the module body is still evaluating, so naming a `const` declared
2793
+ * further down throws at import time with a clean typecheck.
2794
+ */
2795
+ static readonly layer: Layer.Layer<RepositorySecurity, never, GitHubClient>;
2796
+ /** An in-memory double; unstubbed members die naming themselves. */
2797
+ static readonly makeTest: (overrides?: Partial<RepositorySecurityShape>) => RepositorySecurityShape;
2798
+ /** {@link RepositorySecurity.makeTest} behind a `Layer`. */
2799
+ static readonly layerTest: (overrides?: Partial<RepositorySecurityShape>) => Layer.Layer<RepositorySecurity>;
2800
+ }
2801
+ //#endregion
2802
+ //#region src/RepositoryVariable.d.ts
2803
+ /**
2804
+ * A variable, as listing returns it.
2805
+ *
2806
+ * @remarks
2807
+ * Unlike a secret this carries its **value**: variables are readable, so a
2808
+ * consumer comparing desired against live can detect an *edited* variable and
2809
+ * not merely a deleted one. Discarding the value in a projection here would
2810
+ * throw that away silently.
2811
+ *
2812
+ * @public
2813
+ */
2814
+ interface VariableInfo {
2815
+ readonly name: string;
2816
+ readonly value: string;
2817
+ }
2818
+ /**
2819
+ * Repository and environment variables.
2820
+ *
2821
+ * @public
2822
+ */
2823
+ interface RepositoryVariableShape {
2824
+ /**
2825
+ * Create or update one repository variable.
2826
+ *
2827
+ * @remarks
2828
+ * GitHub has **no upsert** for variables: creating uses `POST` on the
2829
+ * collection and updating uses `PATCH` on the item, and each fails if used
2830
+ * for the other case. So this reads first and branches — one extra request
2831
+ * per write, and the reason it is not optional.
2832
+ *
2833
+ * The read is **by name**, not a listing: GitHub answers 404 for an absent
2834
+ * variable, so the check is constant cost rather than growing with a
2835
+ * repository that has nothing to do with the variable being written. Only
2836
+ * `notFound` is absorbed — a 403 from a mis-scoped token still fails, where
2837
+ * treating any error as absence would turn a permissions problem into a
2838
+ * spurious create.
2839
+ *
2840
+ * **The 404-for-absent behaviour is documented, not probed.** Neither this
2841
+ * suite nor the first consumer's has issued this read against real GitHub —
2842
+ * both run against doubles.
2843
+ *
2844
+ * Only `notFound` selects the create branch: a successful read selects the
2845
+ * update branch, and any other failure propagates rather than being guessed
2846
+ * at. So if GitHub answers something *other* than 404 for an absent
2847
+ * variable, the write does not silently take the wrong branch — it either
2848
+ * `PATCH`es a variable that is not there, or fails with the error GitHub
2849
+ * actually sent. Read either as evidence about this assumption rather than
2850
+ * about the caller.
2851
+ */
2852
+ readonly set: (name: string, value: string) => Effect.Effect<void, GitHubError, Repo>;
2853
+ /** The repository's variables, with their values. */
2854
+ readonly list: () => Effect.Effect<ReadonlyArray<VariableInfo>, GitHubError, Repo>;
2855
+ /** Remove one repository variable. */
2856
+ readonly delete: (name: string) => Effect.Effect<void, GitHubError, Repo>;
2857
+ /** Create or update one environment variable, branching the same way. */
2858
+ readonly setForEnvironment: (environment: string, name: string, value: string) => Effect.Effect<void, GitHubError, Repo>;
2859
+ /** One environment's variables, with their values. */
2860
+ readonly listForEnvironment: (environment: string) => Effect.Effect<ReadonlyArray<VariableInfo>, GitHubError, Repo>;
2861
+ /** Remove one environment variable. */
2862
+ readonly deleteForEnvironment: (environment: string, name: string) => Effect.Effect<void, GitHubError, Repo>;
2863
+ }
2864
+ declare const RepositoryVariable_base: Context.ServiceClass<RepositoryVariable, "@effected/github/RepositoryVariable", RepositoryVariableShape>;
2865
+ /**
2866
+ * Repository and environment variables.
2867
+ *
2868
+ * @remarks
2869
+ * No encryption and no public key, unlike secrets — but also **no upsert**,
2870
+ * which is the asymmetry worth knowing: every write costs a read first, because
2871
+ * the create and update routes are different endpoints with different verbs and
2872
+ * neither tolerates the other's case.
2873
+ *
2874
+ * @public
2875
+ */
2876
+ declare class RepositoryVariable extends RepositoryVariable_base {
2877
+ /**
2878
+ * @remarks
2879
+ * `(client) => make(client)` rather than `make`: a static initializer runs
2880
+ * while the module body is still evaluating, so naming a `const` declared
2881
+ * further down throws at import time with a clean typecheck.
2882
+ */
2883
+ static readonly layer: Layer.Layer<RepositoryVariable, never, GitHubClient>;
2884
+ /** An in-memory double; unstubbed members die naming themselves. */
2885
+ static readonly makeTest: (overrides?: Partial<RepositoryVariableShape>) => RepositoryVariableShape;
2886
+ /** {@link RepositoryVariable.makeTest} behind a `Layer`. */
2887
+ static readonly layerTest: (overrides?: Partial<RepositoryVariableShape>) => Layer.Layer<RepositoryVariable>;
2888
+ }
2889
+ //#endregion
2890
+ //#region src/Ruleset.d.ts
2891
+ /**
2892
+ * A ruleset, as listing returns it.
2893
+ *
2894
+ * @remarks
2895
+ * `source_type` is the field that matters and the one easiest to drop from a
2896
+ * projection: a repository's ruleset listing includes rulesets **inherited from
2897
+ * the organization**, and they are indistinguishable from the repository's own
2898
+ * without it.
2899
+ *
2900
+ * @public
2901
+ */
2902
+ interface RulesetInfo {
2903
+ readonly id: number;
2904
+ readonly name: string;
2905
+ /** `"Repository"` for the repository's own, `"Organization"` for an inherited one. */
2906
+ readonly source_type?: string | undefined;
2907
+ }
2908
+ /**
2909
+ * What a ruleset write sends.
2910
+ *
2911
+ * @remarks
2912
+ * `conditions`, `rules` and `bypass_actors` are open records: GitHub's rule
2913
+ * vocabulary is large, versioned and expanding, and pinning it here would date
2914
+ * the package rather than protect the caller.
2915
+ *
2916
+ * @public
2917
+ */
2918
+ interface RulesetPayload {
2919
+ readonly name: string;
2920
+ readonly target: string;
2921
+ readonly enforcement: string;
2922
+ readonly conditions?: unknown;
2923
+ readonly rules?: unknown;
2924
+ readonly bypass_actors?: unknown;
2925
+ }
2926
+ /**
2927
+ * Repository rulesets, and the lookups their bypass actors need.
2928
+ *
2929
+ * @public
2930
+ */
2931
+ interface RulesetShape {
2932
+ /**
2933
+ * Create or update a ruleset, matched by name.
2934
+ *
2935
+ * @remarks
2936
+ * A ruleset has **no natural key** on GitHub's side — only a numeric id
2937
+ * assigned at creation — so this matches on `name`. Renaming a ruleset in a
2938
+ * caller's configuration therefore creates a second one rather than renaming
2939
+ * the first; removing the orphan is the caller's cleanup pass.
2940
+ */
2941
+ readonly upsert: (payload: RulesetPayload) => Effect.Effect<void, GitHubError, Repo>;
2942
+ /** Every ruleset the repository sees, its own and the organization's. */
2943
+ readonly list: () => Effect.Effect<ReadonlyArray<RulesetInfo>, GitHubError, Repo>;
2944
+ /** Remove one ruleset by id. */
2945
+ readonly delete: (rulesetId: number) => Effect.Effect<void, GitHubError, Repo>;
2946
+ /**
2947
+ * A team's numeric id, for a bypass actor.
2948
+ *
2949
+ * @remarks
2950
+ * Org-scoped, sourced from `Repo.owner` — the organization that owns the
2951
+ * repository. A team in a *different* organization is not reachable here and
2952
+ * should not be: `Repo` would be lying about the scope.
2953
+ */
2954
+ readonly teamId: (slug: string) => Effect.Effect<number, GitHubError, Repo>;
2955
+ /** An organization role's numeric id, for a bypass actor. */
2956
+ readonly roleId: (name: string) => Effect.Effect<number, GitHubError, Repo>;
2957
+ }
2958
+ declare const Ruleset_base: Context.ServiceClass<Ruleset, "@effected/github/Ruleset", RulesetShape>;
2959
+ /**
2960
+ * Repository rulesets.
2961
+ *
2962
+ * @remarks
2963
+ * ## An inherited ruleset is never written to
2964
+ *
2965
+ * `GET /repos/{owner}/{repo}/rulesets` returns rulesets **inherited from the
2966
+ * organization** alongside the repository's own. Matching by name alone lets a
2967
+ * repository-scoped call issue a `PUT` against the organization's ruleset id —
2968
+ * rewriting policy for **every repository the organization owns**, from a caller
2969
+ * that never mentioned the organization.
2970
+ *
2971
+ * {@link RulesetShape.upsert} filters on `source_type` before matching, so an
2972
+ * inherited ruleset can never be the target of a write. This arrived as a fix
2973
+ * for a live defect in the consumer this module was ported from, where the
2974
+ * filter was absent.
2975
+ *
2976
+ * @public
2977
+ */
2978
+ declare class Ruleset extends Ruleset_base {
2979
+ /**
2980
+ * @remarks
2981
+ * `(client) => make(client)` rather than `make`: a static initializer runs
2982
+ * while the module body is still evaluating, so naming a `const` declared
2983
+ * further down throws at import time with a clean typecheck.
2984
+ */
2985
+ static readonly layer: Layer.Layer<Ruleset, never, GitHubClient>;
2986
+ /** An in-memory double; unstubbed members die naming themselves. */
2987
+ static readonly makeTest: (overrides?: Partial<RulesetShape>) => RulesetShape;
2988
+ /** {@link Ruleset.makeTest} behind a `Layer`. */
2989
+ static readonly layerTest: (overrides?: Partial<RulesetShape>) => Layer.Layer<Ruleset>;
2990
+ }
2991
+ //#endregion
2348
2992
  //#region src/TokenPermissions.d.ts
2349
2993
  /**
2350
2994
  * How much access a permission grants.
@@ -2488,6 +3132,29 @@ declare class WorkflowRunStatus extends WorkflowRunStatus_base {
2488
3132
  /** Has the run finished, whatever the outcome? */
2489
3133
  get isDone(): boolean;
2490
3134
  }
3135
+ /**
3136
+ * One workflow defined in the repository.
3137
+ *
3138
+ * @remarks
3139
+ * `state` is GitHub's own value — `active`, `disabled_manually`,
3140
+ * `disabled_inactivity`, and so on. It is reported rather than interpreted:
3141
+ * whether a *disabled* workflow counts for a given GitHub feature is that
3142
+ * feature's rule, not this package's, and encoding a guess here would put an
3143
+ * unverified server-side behaviour in a library that cannot test it. Callers
3144
+ * that care filter on it themselves.
3145
+ *
3146
+ * @public
3147
+ */
3148
+ interface WorkflowInfo {
3149
+ /** The workflow's numeric id, usable as `workflow_id` on other routes. */
3150
+ readonly id: number;
3151
+ /** The workflow's display name. */
3152
+ readonly name: string;
3153
+ /** Repository-relative path, e.g. `.github/workflows/ci.yml`. */
3154
+ readonly path: string;
3155
+ /** GitHub's state string; see the remarks above before branching on it. */
3156
+ readonly state: string;
3157
+ }
2491
3158
  /**
2492
3159
  * How long to wait for a dispatched run.
2493
3160
  *
@@ -2508,6 +3175,21 @@ interface WorkflowDispatchShape {
2508
3175
  /** Fire a `workflow_dispatch` event. GitHub answers 204 with no run id. */
2509
3176
  readonly dispatch: (workflow: string, ref: string, inputs?: Record<string, string>) => Effect.Effect<void, GitHubError, Repo>;
2510
3177
  readonly runStatus: (runId: number) => Effect.Effect<WorkflowRunStatus, GitHubError, Repo>;
3178
+ /**
3179
+ * Every workflow defined in the repository.
3180
+ *
3181
+ * @remarks
3182
+ * The question this answers is "does this repository have workflows at all",
3183
+ * which nothing else in the package could ask: repository *languages* come
3184
+ * from linguist and can never report `actions`, while GitHub validates that
3185
+ * language against workflow **files**. A consumer offering CodeQL setup
3186
+ * otherwise has to either request `actions` blindly and absorb a 422, or
3187
+ * drop it for every repository including the ones where it is valid.
3188
+ *
3189
+ * An empty array is the honest answer for a repository with no workflows,
3190
+ * not an error.
3191
+ */
3192
+ readonly list: Effect.Effect<ReadonlyArray<WorkflowInfo>, GitHubError, Repo>;
2511
3193
  /**
2512
3194
  * Dispatch, find the run it created, and wait for it to finish.
2513
3195
  *
@@ -2536,5 +3218,5 @@ declare class WorkflowDispatch extends WorkflowDispatch_base {
2536
3218
  static readonly layerTest: (overrides?: Partial<WorkflowDispatchShape>) => Layer.Layer<WorkflowDispatch>;
2537
3219
  }
2538
3220
  //#endregion
2539
- export { Annotation, AnnotationLevel, type AppCredentials, AppIdentity, ArtifactMetadata, type ArtifactMetadataShape, Attestation, AttestationListEntry, AttestationRecord, type AttestationShape, BotIdentity, type BranchOutcome, CheckConclusion, CheckRun, CheckRunOutput, CheckRunRef, type CheckRunShape, CommentMarker, CommentRecord, CommitComparison, CommitFile, CommitRef, CommitSummary, type ConcludeCheckRun, ExtraPermission, FileChange, FileContent, FileDeletion, FileMode, FileStatus, GitBranch, type GitBranchShape, GitCommit, type GitCommitShape, GitHubApp, GitHubAppError, type GitHubAppOptions, type GitHubAppShape, GitHubClient, type GitHubClientOptions, type GitHubClientShape, GitHubCommit, type GitHubCommitShape, GitHubContent, type GitHubContentShape, GitHubError, GitHubErrorKind, type GitHubFixtures, GitHubGraphQLError, GitHubIssue, type GitHubIssueShape, GitHubRelease, type GitHubReleaseShape, GitHubRepository, type GitHubRepositoryShape, GitTag, type GitTagShape, GraphQLDocument, GraphQLErrorEntry, Installation, InstallationToken, InvalidRepoRefError, IssueInfo, type LatestSemverOptions, LinkedIssue, MergeMethod, PageOptions, PermissionGap, PermissionLevel, PermissionResult, type PollOptions, PullRequest, PullRequestComment, type PullRequestCommentShape, PullRequestInfo, type PullRequestShape, RateLimitSnapshot, ReleaseAsset, ReleaseInfo, Repo, RepoRef, type RepositoryPatch, type RepositorySettings, type Data as RestData, type RequestExtras as RestExtras, type Item as RestItem, type PaginatingRoute as RestPaginatingRoute, type Params as RestParams, type Response as RestResponse, type Route as RestRoute, RetryPolicy, type RetryableFailure, SemverTag, StorageRecordInput, TagRef, TokenPermissionError, TokenPermissions, type TokenRequest, type UpsertedPullRequest, type VersionFromTag, WorkflowDispatch, type WorkflowDispatchShape, WorkflowRunStatus, versionFromTag };
3221
+ export { Annotation, AnnotationLevel, type AppCredentials, AppIdentity, type AppliedSettings, ArtifactMetadata, type ArtifactMetadataShape, Attestation, AttestationListEntry, AttestationRecord, type AttestationShape, BotIdentity, type BranchOutcome, CheckConclusion, CheckRun, CheckRunOutput, CheckRunRef, type CheckRunShape, CodeScanning, type CodeScanningSetup, type CodeScanningShape, CommentMarker, CommentRecord, CommitComparison, CommitFile, CommitRef, CommitSummary, type ConcludeCheckRun, DeploymentEnvironment, type DeploymentEnvironmentInfo, type DeploymentEnvironmentShape, ExtraPermission, FileChange, FileContent, FileDeletion, FileMode, FileStatus, GRAPHQL_ONLY_SETTINGS, GitBranch, type GitBranchShape, GitCommit, type GitCommitShape, GitHubApp, GitHubAppError, type GitHubAppOptions, type GitHubAppShape, GitHubClient, type GitHubClientOptions, type GitHubClientShape, GitHubCommit, type GitHubCommitShape, GitHubContent, type GitHubContentShape, GitHubError, GitHubErrorKind, type GitHubFixtures, GitHubGraphQLError, GitHubIssue, type GitHubIssueShape, GitHubRelease, type GitHubReleaseShape, GitHubRepository, type GitHubRepositoryShape, GitTag, type GitTagShape, GraphQLDocument, GraphQLErrorEntry, Installation, InstallationToken, InvalidRepoRefError, IssueInfo, type LatestSemverOptions, LinkedIssue, MergeMethod, type OwnerType, PageOptions, PermissionGap, PermissionLevel, PermissionResult, type PollOptions, PullRequest, PullRequestComment, type PullRequestCommentShape, PullRequestInfo, type PullRequestShape, RateLimitSnapshot, type RecordedCall, ReleaseAsset, ReleaseInfo, Repo, RepoRef, type RepositoryPatch, RepositorySecret, type RepositorySecretShape, RepositorySecurity, type RepositorySecurityShape, type RepositorySettings, RepositoryVariable, type RepositoryVariableShape, type Data as RestData, type RequestExtras as RestExtras, type Item as RestItem, type PaginatingRoute as RestPaginatingRoute, type Params as RestParams, type Response as RestResponse, type Route as RestRoute, RetryPolicy, type RetryableFailure, Ruleset, type RulesetInfo, type RulesetPayload, type RulesetShape, SECURITY_ANALYSIS_STATUS_FIELDS, type SecretInfo, type SecretScope, SemverTag, StorageRecordInput, TagRef, TokenPermissionError, TokenPermissions, type TokenRequest, type UpsertedPullRequest, type VariableInfo, type VersionFromTag, WorkflowDispatch, type WorkflowDispatchShape, type WorkflowInfo, WorkflowRunStatus, transformSecurityAndAnalysis, versionFromTag };
2540
3222
  //# sourceMappingURL=index.d.ts.map