From f939dca780e7b46cd496775985429be1eefd6cab Mon Sep 17 00:00:00 2001 From: WilcoLouwerse Date: Thu, 15 Oct 2026 11:52:07 +0200 Subject: [PATCH 1/2] chore(openspec): archive github-provider-code-search after the live harvest Task 2.4 is done: the authenticated harvest against real GitHub ran on the WOO-585 rig through a brokered github credential (24 of 24 shards, 698 components on 2026-10-01, 902 on 2026-10-13). The allow-rule requirement joins the main spec credential-broker, the change moves to the archive, and the test's @spec tag points at the main spec. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../design.md | 0 .../proposal.md | 0 .../specs/credential-broker/spec.md | 0 .../tasks.md | 2 +- openspec/specs/credential-broker/spec.md | 34 +++++++++++++++++++ .../Credential/GithubCodeSearchRuleTest.php | 2 +- 6 files changed, 36 insertions(+), 2 deletions(-) rename openspec/changes/{github-provider-code-search => archive/2026-10-15-github-provider-code-search}/design.md (100%) rename openspec/changes/{github-provider-code-search => archive/2026-10-15-github-provider-code-search}/proposal.md (100%) rename openspec/changes/{github-provider-code-search => archive/2026-10-15-github-provider-code-search}/specs/credential-broker/spec.md (100%) rename openspec/changes/{github-provider-code-search => archive/2026-10-15-github-provider-code-search}/tasks.md (78%) diff --git a/openspec/changes/github-provider-code-search/design.md b/openspec/changes/archive/2026-10-15-github-provider-code-search/design.md similarity index 100% rename from openspec/changes/github-provider-code-search/design.md rename to openspec/changes/archive/2026-10-15-github-provider-code-search/design.md diff --git a/openspec/changes/github-provider-code-search/proposal.md b/openspec/changes/archive/2026-10-15-github-provider-code-search/proposal.md similarity index 100% rename from openspec/changes/github-provider-code-search/proposal.md rename to openspec/changes/archive/2026-10-15-github-provider-code-search/proposal.md diff --git a/openspec/changes/github-provider-code-search/specs/credential-broker/spec.md b/openspec/changes/archive/2026-10-15-github-provider-code-search/specs/credential-broker/spec.md similarity index 100% rename from openspec/changes/github-provider-code-search/specs/credential-broker/spec.md rename to openspec/changes/archive/2026-10-15-github-provider-code-search/specs/credential-broker/spec.md diff --git a/openspec/changes/github-provider-code-search/tasks.md b/openspec/changes/archive/2026-10-15-github-provider-code-search/tasks.md similarity index 78% rename from openspec/changes/github-provider-code-search/tasks.md rename to openspec/changes/archive/2026-10-15-github-provider-code-search/tasks.md index 666594903d..e4f40990d7 100644 --- a/openspec/changes/github-provider-code-search/tasks.md +++ b/openspec/changes/archive/2026-10-15-github-provider-code-search/tasks.md @@ -8,4 +8,4 @@ - [x] 2.1 `tests/Unit/Service/Credential/GithubCodeSearchRuleTest.php`: drives `CredentialBrokerService::request()` with the shipped catalogue. `GET /search/code` with and without a query string, and `GET /repos/{owner}/{repo}/contents/publiccode.yml`, reach the client host-locked to `api.github.com` with the token header. POST/PUT/DELETE on `/search/code`, `GET /search/commits`, `GET /search/users`, `GET /search/code/extra` and `GET /search/codes` are refused with no outbound call. Fails without the rule (checked by removing it: 3 of 11 red). - [x] 2.2 Raise the rule-count pin in `DoffinProviderTest` from 18 to 19. - [x] 2.3 Live on the :8096 stack: a `github` credential, brokered `GET /search/code` reaches the outbound call (no allow-rule refusal), `POST /search/code` and `GET /search/commits` are refused. -- [ ] 2.4 Authenticated harvest against real GitHub with Ruben's token (coordinator; no token exists yet). +- [x] 2.4 Authenticated harvest against real GitHub with Ruben's token (coordinator; no token exists yet). (verified: WOO-585 rig against real github.com, brokered through the `github` credential `github-publiccode`, 24 of 24 shards, 698 components on 2026-10-01 and 902 on 2026-10-13; token owner not recorded) diff --git a/openspec/specs/credential-broker/spec.md b/openspec/specs/credential-broker/spec.md index 868e2367fd..fd062b90eb 100644 --- a/openspec/specs/credential-broker/spec.md +++ b/openspec/specs/credential-broker/spec.md @@ -520,3 +520,37 @@ throw); the app's OR app-key onboarding and the broker SHALL continue unchanged. - **WHEN** the onboarding hook runs while Doriath is absent, disabled, or its `ApplicationService` is unloadable - **THEN** it logs/outputs a warning and completes without error - **AND** the app's OpenRegister app-key onboarding and the credential broker continue to operate unchanged + +### Requirement: GitHub code search allow-rule + +The provider catalogue's `github` entry SHALL permit `GET /search/code` so a +caller can find files by name across every repository the token can see. The +rule SHALL match the path exactly (after the broker strips the query string), +SHALL be GET only, and SHALL NOT grant any other search endpoint or any sub-path +of `/search/code`. The per-file read stays covered by the existing +`GET /repos/*` rule; no additional contents rule is added. + +#### Scenario: Code search with a query and a page is allowed + +- **WHEN** a brokered call for a `github` credential requests + `GET /search/code?q=filename%3Apubliccode.yml+path%3A%2F&per_page=100&page=3` +- **THEN** the query string is stripped for rule matching and the + `GET /search/code` rule matches +- **AND** the outbound URL is + `https://api.github.com/search/code?q=filename%3Apubliccode.yml+path%3A%2F&per_page=100&page=3` + with the broker-injected `Authorization` header + +#### Scenario: The per-file contents read stays allowed + +- **WHEN** a brokered call requests + `GET /repos/ConductionNL/opencatalogi/contents/publiccode.yml?ref=main` +- **THEN** the existing `GET /repos/*` rule matches and the call proceeds + host-locked to `api.github.com` + +#### Scenario: Writes and other searches stay refused + +- **WHEN** a brokered call requests `POST`, `PUT` or `DELETE` on `/search/code`, + or `GET /search/commits`, `GET /search/users`, `GET /search/code/extra` or + `GET /search/codes` +- **THEN** the broker refuses it with `no allow-rule matches` and makes no + outbound call diff --git a/tests/Unit/Service/Credential/GithubCodeSearchRuleTest.php b/tests/Unit/Service/Credential/GithubCodeSearchRuleTest.php index c30d5ab131..0f695ba7f0 100644 --- a/tests/Unit/Service/Credential/GithubCodeSearchRuleTest.php +++ b/tests/Unit/Service/Credential/GithubCodeSearchRuleTest.php @@ -21,7 +21,7 @@ * * @link https://conduction.nl * - * @spec openspec/changes/github-provider-code-search/specs/credential-broker/spec.md#requirement-github-code-search-allow-rule + * @spec openspec/specs/credential-broker/spec.md#requirement-github-code-search-allow-rule */ declare(strict_types=1); From 0ff6ac71e8af0f00f75ef6f5bbf20e8de3421d91 Mon Sep 17 00:00:00 2001 From: WilcoLouwerse Date: Thu, 15 Oct 2026 12:28:24 +0200 Subject: [PATCH 2/2] docs(openspec): refusal scenario names the static 403; task 2.4 states its token The GitHub code search refusal scenario said the broker refuses with 'no allow-rule matches'. That string is the logged reason; the caller gets the static 403 'Request not permitted'. Fixed in the main spec and in the archived delta. Task 2.4 no longer says no token exists next to its verification, and names the token the harvest used. Closes review findings: refusal scenario promises a response text the broker never returns; ticked task 2.4 still says no token exists yet. Co-Authored-By: Claude Opus 5.5 --- .../specs/credential-broker/spec.md | 4 ++-- .../archive/2026-10-15-github-provider-code-search/tasks.md | 2 +- openspec/specs/credential-broker/spec.md | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openspec/changes/archive/2026-10-15-github-provider-code-search/specs/credential-broker/spec.md b/openspec/changes/archive/2026-10-15-github-provider-code-search/specs/credential-broker/spec.md index 0c18185b86..9b37223789 100644 --- a/openspec/changes/archive/2026-10-15-github-provider-code-search/specs/credential-broker/spec.md +++ b/openspec/changes/archive/2026-10-15-github-provider-code-search/specs/credential-broker/spec.md @@ -31,5 +31,5 @@ of `/search/code`. The per-file read stays covered by the existing - **WHEN** a brokered call requests `POST`, `PUT` or `DELETE` on `/search/code`, or `GET /search/commits`, `GET /search/users`, `GET /search/code/extra` or `GET /search/codes` -- **THEN** the broker refuses it with `no allow-rule matches` and makes no - outbound call +- **THEN** the broker refuses it with the static 403 (`Request not permitted`; + the reason is logged, never returned) and makes no outbound call diff --git a/openspec/changes/archive/2026-10-15-github-provider-code-search/tasks.md b/openspec/changes/archive/2026-10-15-github-provider-code-search/tasks.md index e4f40990d7..3ff319f95c 100644 --- a/openspec/changes/archive/2026-10-15-github-provider-code-search/tasks.md +++ b/openspec/changes/archive/2026-10-15-github-provider-code-search/tasks.md @@ -8,4 +8,4 @@ - [x] 2.1 `tests/Unit/Service/Credential/GithubCodeSearchRuleTest.php`: drives `CredentialBrokerService::request()` with the shipped catalogue. `GET /search/code` with and without a query string, and `GET /repos/{owner}/{repo}/contents/publiccode.yml`, reach the client host-locked to `api.github.com` with the token header. POST/PUT/DELETE on `/search/code`, `GET /search/commits`, `GET /search/users`, `GET /search/code/extra` and `GET /search/codes` are refused with no outbound call. Fails without the rule (checked by removing it: 3 of 11 red). - [x] 2.2 Raise the rule-count pin in `DoffinProviderTest` from 18 to 19. - [x] 2.3 Live on the :8096 stack: a `github` credential, brokered `GET /search/code` reaches the outbound call (no allow-rule refusal), `POST /search/code` and `GET /search/commits` are refused. -- [x] 2.4 Authenticated harvest against real GitHub with Ruben's token (coordinator; no token exists yet). (verified: WOO-585 rig against real github.com, brokered through the `github` credential `github-publiccode`, 24 of 24 shards, 698 components on 2026-10-01 and 902 on 2026-10-13; token owner not recorded) +- [x] 2.4 Authenticated harvest against real GitHub (coordinator). (verified: WOO-585 rig against real github.com, brokered through the `github` credential `github-publiccode` holding Wilco's own GitHub token, 24 of 24 shards, 698 components on 2026-10-01 and 902 on 2026-10-13 (WOO-585 test plan, scenario 4)) diff --git a/openspec/specs/credential-broker/spec.md b/openspec/specs/credential-broker/spec.md index fd062b90eb..0ba1c2b6b7 100644 --- a/openspec/specs/credential-broker/spec.md +++ b/openspec/specs/credential-broker/spec.md @@ -552,5 +552,5 @@ of `/search/code`. The per-file read stays covered by the existing - **WHEN** a brokered call requests `POST`, `PUT` or `DELETE` on `/search/code`, or `GET /search/commits`, `GET /search/users`, `GET /search/code/extra` or `GET /search/codes` -- **THEN** the broker refuses it with `no allow-rule matches` and makes no - outbound call +- **THEN** the broker refuses it with the static 403 (`Request not permitted`; + the reason is logged, never returned) and makes no outbound call