specguard-mcp 0.1.16 → 0.1.18
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 +82 -29
- package/dist/src/config.d.ts +3 -3
- package/dist/src/config.js +6 -6
- package/dist/src/config.js.map +1 -1
- package/dist/src/tools/add-repository-member.js +16 -6
- package/dist/src/tools/add-repository-member.js.map +1 -1
- package/dist/src/tools/create-repository-api-key.js +13 -5
- package/dist/src/tools/create-repository-api-key.js.map +1 -1
- package/dist/src/tools/list-repository-agent-keys-presented-revoked.js +12 -4
- package/dist/src/tools/list-repository-agent-keys-presented-revoked.js.map +1 -1
- package/dist/src/tools/list-repository-agent-keys.js +12 -4
- package/dist/src/tools/list-repository-agent-keys.js.map +1 -1
- package/dist/src/tools/list-repository-members.js +11 -5
- package/dist/src/tools/list-repository-members.js.map +1 -1
- package/dist/src/tools/remove-repository-member.js +11 -4
- package/dist/src/tools/remove-repository-member.js.map +1 -1
- package/dist/src/tools/rename-repository.d.ts +8 -2
- package/dist/src/tools/rename-repository.js +16 -6
- package/dist/src/tools/rename-repository.js.map +1 -1
- package/dist/src/tools/revoke-repository-agent-key.js +12 -4
- package/dist/src/tools/revoke-repository-agent-key.js.map +1 -1
- package/dist/src/tools/revoke-repository-api-key.js +11 -5
- package/dist/src/tools/revoke-repository-api-key.js.map +1 -1
- package/dist/src/tools/update-repository-member-permissions.js +13 -4
- package/dist/src/tools/update-repository-member-permissions.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,8 +34,8 @@ refuses to boot and takes the tools that needed no configuration down with it.
|
|
|
34
34
|
| --- | --- | --- | --- |
|
|
35
35
|
| `SPECGUARD_ENDPOINT` | `get_repository_overview`, `list_repositories`, `add_repository`, `registrable_repositories` | — | your SpecGuard instance's root URL, **including the scheme** — e.g. `https://specguard.example.com`, or `http://localhost:3000`. A value with no scheme is refused by name (`SPECGUARD_ENDPOINT is not a usable URL: "sg.example.com"`) rather than surfacing later as an opaque failure. `SPECGUARD_URL` is accepted as an alias, and is the name every message uses when it is the one you set. A blank value counts as unset, so leaving `SPECGUARD_ENDPOINT` empty in a templated config falls through to `SPECGUARD_URL` instead of suppressing it |
|
|
36
36
|
| `SPECGUARD_API_KEY` | `get_repository_overview`, `near_duplicate_clusters` (default calls) | — | an agent/CI API key (`sgk_…`) issued by that deployment — a **per-repository** key, which is the single repository those tools answer about by default |
|
|
37
|
-
| `SPECGUARD_USER_API_KEY` | `list_repositories` (fallback), `add_repository`, `registrable_repositories`, `remove_repository` (fallback), `create_repository_api_key
|
|
38
|
-
| `SPECGUARD_AGENT_API_KEY` | `list_repositories` (preferred), `remove_repository` (preferred), `get_repository_overview` / `near_duplicate_clusters` **with** `repository` | — | an **agent** API key (`sga_…`), minted from that deployment's account page (Agent keys panel) with an explicit set of repositories and permissions. It speaks for nobody: its reach is exactly the set granted onto it, fixed at mint time, and every read is bounded by that set server-side. This is the credential to give an automated agent — one key, many repositories, none of a person's rights. When it and `SPECGUARD_USER_API_KEY` are both set, `list_repositories` and
|
|
37
|
+
| `SPECGUARD_USER_API_KEY` | `list_repositories` (fallback), `add_repository`, `registrable_repositories`, `remove_repository` (fallback), `create_repository_api_key` (fallback), `revoke_repository_api_key` (fallback), `list_repository_agent_keys` (fallback), `revoke_repository_agent_key` (fallback), `list_repository_agent_keys_presented_revoked` (fallback), `list_repository_members` (fallback), `add_repository_member` (fallback), `update_repository_member_permissions` (fallback), `remove_repository_member` (fallback), `rename_repository` | — | a **user** API key (`sgu_…`), minted from that deployment's account page. A different credential from the one above, not a second place to put the same value: SpecGuard decides which of them a request may use from the token's prefix, before it reads anything, and answers `401` for the other one. Set whichever your tools need — both, if you use both |
|
|
38
|
+
| `SPECGUARD_AGENT_API_KEY` | `list_repositories` (preferred), `remove_repository` (preferred), `create_repository_api_key` (preferred), `revoke_repository_api_key` (preferred), `list_repository_agent_keys` (preferred), `revoke_repository_agent_key` (preferred), `list_repository_agent_keys_presented_revoked` (preferred), `list_repository_members` (preferred), `add_repository_member` (preferred), `update_repository_member_permissions` (preferred), `remove_repository_member` (preferred), `get_repository_overview` / `near_duplicate_clusters` **with** `repository` | — | an **agent** API key (`sga_…`), minted from that deployment's account page (Agent keys panel) with an explicit set of repositories and permissions. It speaks for nobody: its reach is exactly the set granted onto it, fixed at mint time, and every read is bounded by that set server-side. This is the credential to give an automated agent — one key, many repositories, none of a person's rights. When it and `SPECGUARD_USER_API_KEY` are both set, every repository-administration tool that answers either key — `list_repositories`, `remove_repository`, the members tools and the key-lifecycle tools — uses **this** one, so discovery stays inside the set the other tools can reach |
|
|
39
39
|
| `SPECGUARD_LINT_COMMAND` | `lint_intent_annotations` | `specguard-lint` | the command that runs the linter. Most Ruby projects need `bundle exec specguard-lint` |
|
|
40
40
|
| `SPECGUARD_TIMEOUT_MS` | HTTP tools | `30000` | how long a call to SpecGuard may take |
|
|
41
41
|
|
|
@@ -410,7 +410,8 @@ never used.
|
|
|
410
410
|
Registering a repository is `add_repository`, below — it reads `SPECGUARD_USER_API_KEY` (an
|
|
411
411
|
`sgu_…` key, which this tool also accepts but does not require) and takes the `full_name` this
|
|
412
412
|
tool reports. Removal and the key lifecycle (`remove_repository`,
|
|
413
|
-
`create_repository_api_key`, `revoke_repository_api_key`) are below too, on the same
|
|
413
|
+
`create_repository_api_key`, `revoke_repository_api_key`) are below too, on the same
|
|
414
|
+
either-credential rule; a tool
|
|
414
415
|
here is a promise the agent will act on, so each waits for the capability rather than the other way
|
|
415
416
|
round.
|
|
416
417
|
|
|
@@ -592,9 +593,15 @@ The body comes back as SpecGuard serves it: an `api_key` block (`name`, `token`,
|
|
|
592
593
|
Authorization is the `keys_manage` capability; a member without it is refused `403` with SpecGuard's
|
|
593
594
|
own sentence, verbatim.
|
|
594
595
|
|
|
595
|
-
It reads
|
|
596
|
-
|
|
597
|
-
|
|
596
|
+
It reads either of two credentials, whichever is set — and a different one from the `sgk_…` key
|
|
597
|
+
`get_repository_overview` uses. `SPECGUARD_AGENT_API_KEY` (`sga_…`) when it is set: the call then
|
|
598
|
+
reaches only the repositories granted onto that key at mint time, and only where the grant carries
|
|
599
|
+
`keys.manage` — a repository outside that set is answered `404` in SpecGuard's own words.
|
|
600
|
+
`SPECGUARD_USER_API_KEY` (`sgu_…`) when no agent key is set: the same **person** key `add_repository`
|
|
601
|
+
reads. With both set the **agent** key wins, so the mint answers inside the same set
|
|
602
|
+
`list_repositories` reports. Minting under the agent credential attributes the new key to the agent
|
|
603
|
+
key's **owner** (the server's `attributed_user` rule), so minted-key counts keep naming a person
|
|
604
|
+
rather than nobody.
|
|
598
605
|
|
|
599
606
|
### `revoke_repository_api_key`
|
|
600
607
|
|
|
@@ -615,9 +622,13 @@ replacement with `create_repository_api_key` and deploy it BEFORE revoking the o
|
|
|
615
622
|
first and the repository's CI is locked out until a human mints a new key in a browser. A `204`
|
|
616
623
|
means the key is revoked.
|
|
617
624
|
|
|
618
|
-
It reads
|
|
619
|
-
|
|
620
|
-
|
|
625
|
+
It reads either of two credentials, whichever is set — and a different one from the `sgk_…` key
|
|
626
|
+
`get_repository_overview` uses. `SPECGUARD_AGENT_API_KEY` (`sga_…`) when it is set: the call then
|
|
627
|
+
reaches only the repositories granted onto that key at mint time, and only where the grant carries
|
|
628
|
+
`keys.manage` — a repository outside that set is answered `404` in SpecGuard's own words.
|
|
629
|
+
`SPECGUARD_USER_API_KEY` (`sgu_…`) when no agent key is set: the same **person** key `add_repository`
|
|
630
|
+
reads. With both set the **agent** key wins, so the revoke answers inside the same set
|
|
631
|
+
`list_repositories` reports.
|
|
621
632
|
|
|
622
633
|
### `list_repository_agent_keys`
|
|
623
634
|
|
|
@@ -640,8 +651,14 @@ arriving is `list_repository_agent_keys_presented_revoked`'s question.
|
|
|
640
651
|
time and nothing persisted it. Authorization is the `keys_manage` capability; a caller without it
|
|
641
652
|
is refused `403` with SpecGuard's own sentence, verbatim.
|
|
642
653
|
|
|
643
|
-
It reads
|
|
644
|
-
`
|
|
654
|
+
It reads either of two credentials, whichever is set — and a different one from the `sgk_…` key
|
|
655
|
+
`get_repository_overview` uses. `SPECGUARD_AGENT_API_KEY` (`sga_…`) when it is set: the call then
|
|
656
|
+
reaches only the repositories granted onto that key at mint time, and only where the grant carries
|
|
657
|
+
`keys.manage` — a repository outside that set is answered `404` in SpecGuard's own words, so an
|
|
658
|
+
agent credential administers the agent keys covering its own set without a person's `sgu_` key.
|
|
659
|
+
`SPECGUARD_USER_API_KEY` (`sgu_…`) when no agent key is set: the same **person** key `add_repository`
|
|
660
|
+
reads. With both set the **agent** key wins, so the answer stays inside the same set
|
|
661
|
+
`list_repositories` reports.
|
|
645
662
|
|
|
646
663
|
### `revoke_repository_agent_key`
|
|
647
664
|
|
|
@@ -667,8 +684,14 @@ or one already revoked, is refused `404`, never a cross-repository cut. Authoriz
|
|
|
667
684
|
`keys_manage` capability; a caller without it is refused `403` with SpecGuard's own sentence,
|
|
668
685
|
verbatim.
|
|
669
686
|
|
|
670
|
-
It reads
|
|
671
|
-
`
|
|
687
|
+
It reads either of two credentials, whichever is set — and a different one from the `sgk_…` key
|
|
688
|
+
`get_repository_overview` uses. `SPECGUARD_AGENT_API_KEY` (`sga_…`) when it is set: the call then
|
|
689
|
+
reaches only the repositories granted onto that key at mint time, and only where the grant carries
|
|
690
|
+
`keys.manage` — a repository outside that set is answered `404` in SpecGuard's own words, so an
|
|
691
|
+
agent credential can cut one of its own kind without a person's `sgu_` key.
|
|
692
|
+
`SPECGUARD_USER_API_KEY` (`sgu_…`) when no agent key is set: the same **person** key `add_repository`
|
|
693
|
+
reads. With both set the **agent** key wins, so the cut answers inside the same set
|
|
694
|
+
`list_repositories` reports.
|
|
672
695
|
|
|
673
696
|
### `list_repository_agent_keys_presented_revoked`
|
|
674
697
|
|
|
@@ -691,8 +714,14 @@ it as the offboarding having fully taken.
|
|
|
691
714
|
time and nothing persisted it. Authorization is the `keys_manage` capability; a caller without it
|
|
692
715
|
is refused `403` with SpecGuard's own sentence, verbatim.
|
|
693
716
|
|
|
694
|
-
It reads
|
|
695
|
-
`
|
|
717
|
+
It reads either of two credentials, whichever is set — and a different one from the `sgk_…` key
|
|
718
|
+
`get_repository_overview` uses. `SPECGUARD_AGENT_API_KEY` (`sga_…`) when it is set: the call then
|
|
719
|
+
reaches only the repositories granted onto that key at mint time, and only where the grant carries
|
|
720
|
+
`keys.manage` — a repository outside that set is answered `404` in SpecGuard's own words, so an
|
|
721
|
+
agent credential can verify its own offboarding without a person's `sgu_` key.
|
|
722
|
+
`SPECGUARD_USER_API_KEY` (`sgu_…`) when no agent key is set: the same **person** key `add_repository`
|
|
723
|
+
reads. With both set the **agent** key wins, so the triage stays inside the same set
|
|
724
|
+
`list_repositories` reports.
|
|
696
725
|
|
|
697
726
|
### `list_repository_members`
|
|
698
727
|
|
|
@@ -714,9 +743,13 @@ Authorization is the `members.manage` capability: a caller who is not a member i
|
|
|
714
743
|
(the repository's existence stays hidden), and a member without `members.manage` is refused `403`
|
|
715
744
|
with SpecGuard's own sentence, verbatim.
|
|
716
745
|
|
|
717
|
-
It reads
|
|
718
|
-
|
|
719
|
-
|
|
746
|
+
It reads either of two credentials, whichever is set — and a different one from the `sgk_…` key
|
|
747
|
+
`get_repository_overview` uses. `SPECGUARD_AGENT_API_KEY` (`sga_…`) when it is set: the call then
|
|
748
|
+
reaches only the repositories granted onto that key at mint time, and only where the grant carries
|
|
749
|
+
`members.manage` — a repository outside that set is answered `404` in SpecGuard's own words.
|
|
750
|
+
`SPECGUARD_USER_API_KEY` (`sgu_…`) when no agent key is set: the same **person** key `add_repository`
|
|
751
|
+
reads. With both set the **agent** key wins, so the answer stays inside the same set
|
|
752
|
+
`list_repositories` reports.
|
|
720
753
|
|
|
721
754
|
### `add_repository_member`
|
|
722
755
|
|
|
@@ -732,7 +765,8 @@ permissions.
|
|
|
732
765
|
Each resolution failure — nobody has signed in as that handle yet, the account is archived, the
|
|
733
766
|
handle is ambiguous, the handle is not a login — arrives as a **distinguishable** 400 message
|
|
734
767
|
naming the exact next move. The grantor recorded on the membership is always the person behind
|
|
735
|
-
`
|
|
768
|
+
the credential — the one an `sgu_…` key speaks for, or the **owner** of the `sga_…` agent key.
|
|
769
|
+
The server stamps it; no argument can name a different one.
|
|
736
770
|
|
|
737
771
|
On success (`201`) the response carries a `member` block whose **`id` is the membership id**
|
|
738
772
|
(alongside `handle`, `permissions`, `granted_by`, `created_at`) — the identifier
|
|
@@ -740,9 +774,15 @@ On success (`201`) the response carries a `member` block whose **`id` is the mem
|
|
|
740
774
|
`members.manage` capability; a member without it is refused `403` with SpecGuard's own sentence,
|
|
741
775
|
verbatim.
|
|
742
776
|
|
|
743
|
-
It reads
|
|
744
|
-
|
|
745
|
-
|
|
777
|
+
It reads either of two credentials, whichever is set — and a different one from the `sgk_…` key
|
|
778
|
+
`get_repository_overview` uses. `SPECGUARD_AGENT_API_KEY` (`sga_…`) when it is set: the call then
|
|
779
|
+
reaches only the repositories granted onto that key at mint time, and only where the grant carries
|
|
780
|
+
`members.manage` — a repository outside that set is answered `404` in SpecGuard's own words.
|
|
781
|
+
`SPECGUARD_USER_API_KEY` (`sgu_…`) when no agent key is set: the same **person** key `add_repository`
|
|
782
|
+
reads. With both set the **agent** key wins, so the grant answers inside the same set
|
|
783
|
+
`list_repositories` reports. Under the agent credential the grant is bounded twice: the key cannot
|
|
784
|
+
grant a permission it does not itself hold — SpecGuard answers `400` naming the over-reach — and
|
|
785
|
+
the membership is recorded against the key's **owner**.
|
|
746
786
|
|
|
747
787
|
### `update_repository_member_permissions`
|
|
748
788
|
|
|
@@ -766,9 +806,15 @@ ids are scoped to the repository (a foreign id is refused `404`). Authorization
|
|
|
766
806
|
`members.manage` capability; a member without it is refused `403` with SpecGuard's own sentence,
|
|
767
807
|
verbatim.
|
|
768
808
|
|
|
769
|
-
It reads
|
|
770
|
-
|
|
771
|
-
|
|
809
|
+
It reads either of two credentials, whichever is set — and a different one from the `sgk_…` key
|
|
810
|
+
`get_repository_overview` uses. `SPECGUARD_AGENT_API_KEY` (`sga_…`) when it is set: the call then
|
|
811
|
+
reaches only the repositories granted onto that key at mint time, and only where the grant carries
|
|
812
|
+
`members.manage` — a repository outside that set is answered `404` in SpecGuard's own words.
|
|
813
|
+
`SPECGUARD_USER_API_KEY` (`sgu_…`) when no agent key is set: the same **person** key `add_repository`
|
|
814
|
+
reads. With both set the **agent** key wins, so the edit answers inside the same set
|
|
815
|
+
`list_repositories` reports. Under the agent credential the replacement set is bounded twice: the
|
|
816
|
+
key cannot grant a permission it does not itself hold — SpecGuard answers `400` naming the
|
|
817
|
+
over-reach — and the re-stamped grantor is the key's **owner**.
|
|
772
818
|
|
|
773
819
|
### `remove_repository_member`
|
|
774
820
|
|
|
@@ -790,9 +836,13 @@ number on the wire, so pass it as a string, not as a number (see the edit tool a
|
|
|
790
836
|
Authorization is the `members.manage` capability; a member without it is refused `403` with
|
|
791
837
|
SpecGuard's own sentence, verbatim.
|
|
792
838
|
|
|
793
|
-
It reads
|
|
794
|
-
|
|
795
|
-
|
|
839
|
+
It reads either of two credentials, whichever is set — and a different one from the `sgk_…` key
|
|
840
|
+
`get_repository_overview` uses. `SPECGUARD_AGENT_API_KEY` (`sga_…`) when it is set: the call then
|
|
841
|
+
reaches only the repositories granted onto that key at mint time, and only where the grant carries
|
|
842
|
+
`members.manage` — a repository outside that set is answered `404` in SpecGuard's own words.
|
|
843
|
+
`SPECGUARD_USER_API_KEY` (`sgu_…`) when no agent key is set: the same **person** key `add_repository`
|
|
844
|
+
reads. With both set the **agent** key wins, so the revoke answers inside the same set
|
|
845
|
+
`list_repositories` reports.
|
|
796
846
|
|
|
797
847
|
### `rename_repository`
|
|
798
848
|
|
|
@@ -810,7 +860,10 @@ is owner-only** — deliberately narrower than removal: a member granted `repo.d
|
|
|
810
860
|
the repository but may not rename it. The owner check also redeems a browser-issued grant valid for
|
|
811
861
|
7 days; a nil or stale one is refused `403` with SpecGuard's own sentence naming the fix
|
|
812
862
|
(re-grant via the browser). A name another repository already holds is refused `400` — `taken`, not
|
|
813
|
-
`409` — verbatim. The `200` body is `{repository: …}`
|
|
863
|
+
`409` — verbatim. The `200` body is `{repository: …}` — the serializer `list_repositories` uses, but a
|
|
864
|
+
rename receipt, not a list entry: it carries the identity fields and `delivery_health`, and
|
|
865
|
+
`latest_run` is absent — an absent key, never a null — deliberately, so the receipt claims nothing
|
|
866
|
+
about the repository's CI state. `list_repositories` is where a run summary comes from.
|
|
814
867
|
|
|
815
868
|
It reads `SPECGUARD_USER_API_KEY` (`sgu_…`) — the same **person** key `add_repository` reads, and
|
|
816
869
|
a different one from the `sgk_…` key `get_repository_overview` uses; `list_repositories` also
|
package/dist/src/config.d.ts
CHANGED
|
@@ -167,9 +167,9 @@ export interface Credential {
|
|
|
167
167
|
/**
|
|
168
168
|
* The `sgk_` key: one repository, and the same variable CI already sets.
|
|
169
169
|
*
|
|
170
|
-
* The 401 wording is
|
|
171
|
-
*
|
|
172
|
-
*
|
|
170
|
+
* The 401 wording states what is true of this kind: keys are per-repository,
|
|
171
|
+
* and a revoked key's 401 identifies the revocation rather than reading as a
|
|
172
|
+
* wrong key. The other two credential kinds carry their own refusals.
|
|
173
173
|
*/
|
|
174
174
|
export declare const REPOSITORY_CREDENTIAL: Credential;
|
|
175
175
|
/**
|
package/dist/src/config.js
CHANGED
|
@@ -33,16 +33,16 @@ export function loadConfig(env = process.env) {
|
|
|
33
33
|
/**
|
|
34
34
|
* The `sgk_` key: one repository, and the same variable CI already sets.
|
|
35
35
|
*
|
|
36
|
-
* The 401 wording is
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
* The 401 wording states what is true of this kind: keys are per-repository,
|
|
37
|
+
* and a revoked key's 401 identifies the revocation rather than reading as a
|
|
38
|
+
* wrong key. The other two credential kinds carry their own refusals.
|
|
39
39
|
*/
|
|
40
40
|
export const REPOSITORY_CREDENTIAL = {
|
|
41
41
|
variable: "SPECGUARD_API_KEY",
|
|
42
42
|
prefix: "sgk_",
|
|
43
43
|
issuedFrom: "issued from its API keys page",
|
|
44
44
|
rejection: "for the repository you are asking about — keys are per-repository, and a " +
|
|
45
|
-
"revoked key
|
|
45
|
+
"revoked key's 401 names the revocation",
|
|
46
46
|
};
|
|
47
47
|
/**
|
|
48
48
|
* The `sgu_` key: a person, and a variable nothing else in the toolchain reads.
|
|
@@ -58,7 +58,7 @@ export const USER_CREDENTIAL = {
|
|
|
58
58
|
issuedFrom: "issued from your account page",
|
|
59
59
|
rejection: "for your own SpecGuard account — a user key speaks for a person and lists what " +
|
|
60
60
|
"that person may open, an sgk_… repository key is refused here without a lookup, " +
|
|
61
|
-
"and a revoked key
|
|
61
|
+
"and a revoked key's 401 names the revocation",
|
|
62
62
|
};
|
|
63
63
|
/**
|
|
64
64
|
* The `sga_` key: an AGENT, and a credential that speaks for nobody.
|
|
@@ -86,7 +86,7 @@ export const AGENT_CREDENTIAL = {
|
|
|
86
86
|
issuedFrom: "issued from your account page's Agent keys panel",
|
|
87
87
|
rejection: "for this agent — an agent key speaks for nobody and reaches only the repository set " +
|
|
88
88
|
"granted onto it at mint time, an sgk_… repository key or an sgu_… user key is refused " +
|
|
89
|
-
"here without a lookup, and a revoked key
|
|
89
|
+
"here without a lookup, and a revoked key's 401 names the revocation",
|
|
90
90
|
};
|
|
91
91
|
/**
|
|
92
92
|
* The name to speak when no variable was set at all — the message is telling
|
package/dist/src/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA4G1C,MAAM,CAAC,MAAM,oBAAoB,GAAsB,CAAC,gBAAgB,CAAC,CAAC;AAC1E,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC;AAEjD,2EAA2E;AAC3E,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC;IAC5D,6EAA6E;IAC7E,qEAAqE;IACrE,4EAA4E;IAC5E,8EAA8E;IAC9E,0EAA0E;IAC1E,6EAA6E;IAC7E,8EAA8E;IAC9E,8EAA8E;IAC9E,6EAA6E;IAC7E,mEAAmE;IACnE,8EAA8E;IAC9E,MAAM,gBAAgB,GACpB,QAAQ,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,KAAK,SAAS;QAC/C,CAAC,CAAC,oBAAoB;QACtB,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,KAAK,SAAS;YAC5C,CAAC,CAAC,eAAe;YACjB,CAAC,CAAC,SAAS,CAAC;IAElB,OAAO;QACL,QAAQ,EAAE,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC/F,gBAAgB;QAChB,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAC1C,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACnD,WAAW,EAAE,QAAQ,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACrD,WAAW,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,oBAAoB;QACxE,gBAAgB,EAAE,eAAe,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,IAAI,0BAA0B;KAC7F,CAAC;AACJ,CAAC;AAkED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAe;IAC/C,QAAQ,EAAE,mBAAmB;IAC7B,MAAM,EAAE,MAAM;IACd,UAAU,EAAE,+BAA+B;IAC3C,SAAS,EACP,2EAA2E;QAC3E,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { postJsonObject,
|
|
1
|
+
import { postJsonObject, requireUserOrAgentApiConfig } from "../support/specguard-api.js";
|
|
2
2
|
import { optionalStringArray, requireString } from "./args.js";
|
|
3
3
|
/**
|
|
4
4
|
* `POST /api/v1/repositories/:repository_id/members` as a tool — shipped in the
|
|
@@ -38,8 +38,9 @@ const addRepositoryMember = {
|
|
|
38
38
|
"SpecGuard refuses each of those with its own sentence, and every other resolution failure " +
|
|
39
39
|
"(nobody has signed in as that handle yet, the account is archived, the handle is ambiguous) " +
|
|
40
40
|
"arrives as a distinguishable 400 message naming the exact next move. " +
|
|
41
|
-
"The grantor recorded on the membership is always the person behind
|
|
42
|
-
"key
|
|
41
|
+
"The grantor recorded on the membership is always the person behind the credential — the one " +
|
|
42
|
+
"an sgu_… key speaks for, or the OWNER of the sga_… agent key. The server stamps it, and no " +
|
|
43
|
+
"argument can name a different one. " +
|
|
43
44
|
"On success (201) the response carries a `member` block whose `id` is the MEMBERSHIP id " +
|
|
44
45
|
"(`handle`, `permissions`, `granted_by`, `created_at` alongside) — the very identifier " +
|
|
45
46
|
"`update_repository_member_permissions` and `remove_repository_member` name. The id is not " +
|
|
@@ -53,8 +54,17 @@ const addRepositoryMember = {
|
|
|
53
54
|
"SpecGuard's own words. " +
|
|
54
55
|
"Takes `repository_id` — the numeric id `list_repositories` reports, not the `org/repo` " +
|
|
55
56
|
"handle. " +
|
|
56
|
-
"
|
|
57
|
-
"
|
|
57
|
+
"It authenticates with EITHER of this server's two member-administration credentials, whichever " +
|
|
58
|
+
"is set: SPECGUARD_AGENT_API_KEY (an sga_… key — the call then reaches only the repositories " +
|
|
59
|
+
"granted onto that key at mint time, and only where the grant carries `members.manage`; a " +
|
|
60
|
+
"repository outside that set answers 404 in SpecGuard's own words, never a probe here) and, " +
|
|
61
|
+
"when that is not set, SPECGUARD_USER_API_KEY (an sgu_… key, the same credential " +
|
|
62
|
+
"`add_repository` writes with). With both set the agent key wins, so the grant answers inside " +
|
|
63
|
+
"the same set `list_repositories` reports. Under the agent credential the grant is bounded " +
|
|
64
|
+
"twice: the key cannot grant a permission it does not itself hold (SpecGuard answers 400 " +
|
|
65
|
+
"naming the over-reach), and the membership is recorded against the key's owner. " +
|
|
66
|
+
"Either way it is a DIFFERENT credential from the sgk_… repository key `get_repository_overview` " +
|
|
67
|
+
"uses.",
|
|
58
68
|
inputSchema: {
|
|
59
69
|
type: "object",
|
|
60
70
|
properties: {
|
|
@@ -88,7 +98,7 @@ const addRepositoryMember = {
|
|
|
88
98
|
const repositoryId = requireString(args["repository_id"], "repository_id");
|
|
89
99
|
const handle = requireString(args["handle"], "handle");
|
|
90
100
|
const permissions = optionalStringArray(args["permissions"], "permissions");
|
|
91
|
-
const api =
|
|
101
|
+
const api = requireUserOrAgentApiConfig(context.config);
|
|
92
102
|
// Top-level `{handle, permissions}` — the shape the controller permits,
|
|
93
103
|
// matching `add_repository`'s stated rule: this is JSON an agent writes,
|
|
94
104
|
// not a Rails form. `permissions` omitted when absent so the server's own
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add-repository-member.js","sourceRoot":"","sources":["../../../src/tools/add-repository-member.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"add-repository-member.js","sourceRoot":"","sources":["../../../src/tools/add-repository-member.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,mBAAmB,GAAmB;IAC1C,IAAI,EAAE,uBAAuB;IAC7B,KAAK,EAAE,uBAAuB;IAC9B,WAAW,EACT,4FAA4F;QAC5F,uBAAuB;QACvB,0FAA0F;QAC1F,4FAA4F;QAC5F,8FAA8F;QAC9F,uEAAuE;QACvE,8FAA8F;QAC9F,6FAA6F;QAC7F,qCAAqC;QACrC,yFAAyF;QACzF,wFAAwF;QACxF,4FAA4F;QAC5F,qFAAqF;QACrF,cAAc;QACd,6FAA6F;QAC7F,yFAAyF;QACzF,0FAA0F;QAC1F,0CAA0C;QAC1C,2FAA2F;QAC3F,yBAAyB;QACzB,yFAAyF;QACzF,UAAU;QACV,iGAAiG;QACjG,8FAA8F;QAC9F,2FAA2F;QAC3F,6FAA6F;QAC7F,kFAAkF;QAClF,+FAA+F;QAC/F,4FAA4F;QAC5F,0FAA0F;QAC1F,kFAAkF;QAClF,kGAAkG;QAClG,OAAO;IACT,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,0EAA0E;oBAC1E,qEAAqE;aACxE;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,sFAAsF;oBACtF,mFAAmF;oBACnF,uCAAuC;aAC1C;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,WAAW,EACT,2EAA2E;oBAC3E,mFAAmF;oBACnF,oFAAoF;oBACpF,mBAAmB;aACtB;SACF;QACD,QAAQ,EAAE,CAAC,eAAe,EAAE,QAAQ,CAAC;QACrC,4EAA4E;QAC5E,wEAAwE;QACxE,oCAAoC;QACpC,oBAAoB,EAAE,KAAK;KAC5B;IAED,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO;QACrB,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,WAAW,GAAG,mBAAmB,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC,CAAC;QAE5E,MAAM,GAAG,GAAG,2BAA2B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAExD,wEAAwE;QACxE,yEAAyE;QACzE,0EAA0E;QAC1E,0EAA0E;QAC1E,uEAAuE;QACvE,MAAM,OAAO,GAAG,MAAM,cAAc,CAClC,GAAG,EACH,wBAAwB,kBAAkB,CAAC,YAAY,CAAC,UAAU,EAClE,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAChE,OAAO,CAAC,KAAK,CACd,CAAC;QAEF,2EAA2E;QAC3E,yDAAyD;QACzD,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACtC,UAAU,EAAE,OAAO;SACpB,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { postJsonObject,
|
|
1
|
+
import { postJsonObject, requireUserOrAgentApiConfig } from "../support/specguard-api.js";
|
|
2
2
|
import { optionalString, requireString } from "./args.js";
|
|
3
3
|
/**
|
|
4
4
|
* `POST /api/v1/repositories/:repository_id/api_keys` as a tool — shipped in
|
|
@@ -40,9 +40,17 @@ const createRepositoryApiKey = {
|
|
|
40
40
|
"`name`, which the server defaults when omitted. " +
|
|
41
41
|
"Authorization is the `keys_manage` capability — a member without it is refused 403 " +
|
|
42
42
|
"in SpecGuard's own words. " +
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"`
|
|
43
|
+
"It authenticates with EITHER of this server's two key-administration credentials, whichever " +
|
|
44
|
+
"is set: SPECGUARD_AGENT_API_KEY (an sga_… key — the call then reaches only the repositories " +
|
|
45
|
+
"granted onto that key at mint time, and only where the grant carries `keys.manage`; a " +
|
|
46
|
+
"repository outside that set answers 404 in SpecGuard's own words, never a probe here) and, " +
|
|
47
|
+
"when that is not set, SPECGUARD_USER_API_KEY (an sgu_… key, the same credential " +
|
|
48
|
+
"`add_repository` writes with). With both set the agent key wins, so the mint answers inside " +
|
|
49
|
+
"the same set `list_repositories` reports. Minting under the agent credential attributes the " +
|
|
50
|
+
"new key to the agent key's OWNER (the server's `attributed_user` rule), so minted-key counts " +
|
|
51
|
+
"keep naming a person rather than nobody. " +
|
|
52
|
+
"Either way it is a DIFFERENT credential from the sgk_… repository key " +
|
|
53
|
+
"`get_repository_overview` uses; SpecGuard refuses each in the other's place.",
|
|
46
54
|
inputSchema: {
|
|
47
55
|
type: "object",
|
|
48
56
|
properties: {
|
|
@@ -65,7 +73,7 @@ const createRepositoryApiKey = {
|
|
|
65
73
|
async run(args, context) {
|
|
66
74
|
const repositoryId = requireString(args["repository_id"], "repository_id");
|
|
67
75
|
const name = optionalString(args["name"], "name");
|
|
68
|
-
const api =
|
|
76
|
+
const api = requireUserOrAgentApiConfig(context.config);
|
|
69
77
|
// `name` omitted when absent rather than sent as null, so the server's own
|
|
70
78
|
// `ApiKey::DEFAULT_NAME` default applies — this bridge expresses "no
|
|
71
79
|
// preference", it does not choose on the server's behalf.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-repository-api-key.js","sourceRoot":"","sources":["../../../src/tools/create-repository-api-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"create-repository-api-key.js","sourceRoot":"","sources":["../../../src/tools/create-repository-api-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1F,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,sBAAsB,GAAmB;IAC7C,IAAI,EAAE,2BAA2B;IACjC,KAAK,EAAE,2BAA2B;IAClC,WAAW,EACT,mFAAmF;QACnF,4CAA4C;QAC5C,mFAAmF;QACnF,sFAAsF;QACtF,sFAAsF;QACtF,mFAAmF;QACnF,+EAA+E;QAC/E,sEAAsE;QACtE,iFAAiF;QACjF,+BAA+B;QAC/B,qFAAqF;QACrF,kDAAkD;QAClD,qFAAqF;QACrF,4BAA4B;QAC5B,8FAA8F;QAC9F,8FAA8F;QAC9F,wFAAwF;QACxF,6FAA6F;QAC7F,kFAAkF;QAClF,8FAA8F;QAC9F,8FAA8F;QAC9F,+FAA+F;QAC/F,2CAA2C;QAC3C,wEAAwE;QACxE,8EAA8E;IAChF,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,2EAA2E;oBAC3E,qEAAqE;aACxE;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,gFAAgF;oBAChF,6EAA6E;aAChF;SACF;QACD,QAAQ,EAAE,CAAC,eAAe,CAAC;QAC3B,4EAA4E;QAC5E,+EAA+E;QAC/E,oBAAoB,EAAE,KAAK;KAC5B;IAED,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO;QACrB,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC,CAAC;QAC3E,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;QAElD,MAAM,GAAG,GAAG,2BAA2B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAExD,2EAA2E;QAC3E,qEAAqE;QACrE,0DAA0D;QAC1D,MAAM,OAAO,GAAG,MAAM,cAAc,CAClC,GAAG,EACH,wBAAwB,kBAAkB,CAAC,YAAY,CAAC,WAAW,EACnE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAClC,OAAO,CAAC,KAAK,CACd,CAAC;QAEF,wEAAwE;QACxE,yEAAyE;QACzE,kCAAkC;QAClC,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACtC,UAAU,EAAE,OAAO;SACpB,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getJsonObject,
|
|
1
|
+
import { getJsonObject, requireUserOrAgentApiConfig } from "../support/specguard-api.js";
|
|
2
2
|
import { requireString } from "./args.js";
|
|
3
3
|
/**
|
|
4
4
|
* `GET /api/v1/repositories/:repository_id/agent_keys/presented_revoked` as a
|
|
@@ -53,8 +53,16 @@ const listRepositoryAgentKeysPresentedRevoked = {
|
|
|
53
53
|
"Authorization is the `keys_manage` capability — a caller without it is refused 403 in " +
|
|
54
54
|
"SpecGuard's own words. " +
|
|
55
55
|
"Takes `repository_id` (the numeric id `list_repositories` reports, not the `org/repo` handle). " +
|
|
56
|
-
"
|
|
57
|
-
"
|
|
56
|
+
"It authenticates with EITHER of this server's two key-administration credentials, whichever " +
|
|
57
|
+
"is set: SPECGUARD_AGENT_API_KEY (an sga_… key — the call then reaches only the repositories " +
|
|
58
|
+
"granted onto that key at mint time, and only where the grant carries `keys.manage`; a " +
|
|
59
|
+
"repository outside that set answers 404 in SpecGuard's own words, never a probe here — an " +
|
|
60
|
+
"agent credential verifying its own offboarding needs no person's `sgu_` key to do it) and, " +
|
|
61
|
+
"when that is not set, SPECGUARD_USER_API_KEY (an sgu_… key, the same credential the other " +
|
|
62
|
+
"key-administration tools read). With both set the agent key wins, so the triage stays inside " +
|
|
63
|
+
"the same set `list_repositories` reports. " +
|
|
64
|
+
"Either way it is a DIFFERENT credential from the sgk_… repository key `get_repository_overview` " +
|
|
65
|
+
"uses; SpecGuard refuses each in the other's place.",
|
|
58
66
|
inputSchema: {
|
|
59
67
|
type: "object",
|
|
60
68
|
properties: {
|
|
@@ -72,7 +80,7 @@ const listRepositoryAgentKeysPresentedRevoked = {
|
|
|
72
80
|
},
|
|
73
81
|
async run(args, context) {
|
|
74
82
|
const repositoryId = requireString(args["repository_id"], "repository_id");
|
|
75
|
-
const api =
|
|
83
|
+
const api = requireUserOrAgentApiConfig(context.config);
|
|
76
84
|
const body = await getJsonObject(api, `/api/v1/repositories/${encodeURIComponent(repositoryId)}/agent_keys/presented_revoked`, {}, context.fetch);
|
|
77
85
|
// Passed through unreshaped, the standing rule (`types.ts`: "A thin client
|
|
78
86
|
// that reshapes its upstream is not thin") — and the empty answer passes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-repository-agent-keys-presented-revoked.js","sourceRoot":"","sources":["../../../src/tools/list-repository-agent-keys-presented-revoked.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"list-repository-agent-keys-presented-revoked.js","sourceRoot":"","sources":["../../../src/tools/list-repository-agent-keys-presented-revoked.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,uCAAuC,GAAmB;IAC9D,IAAI,EAAE,8CAA8C;IACpD,KAAK,EAAE,yCAAyC;IAChD,WAAW,EACT,8FAA8F;QAC9F,8FAA8F;QAC9F,6FAA6F;QAC7F,8FAA8F;QAC9F,iEAAiE;QACjE,+FAA+F;QAC/F,oDAAoD;QACpD,+FAA+F;QAC/F,2DAA2D;QAC3D,8FAA8F;QAC9F,sCAAsC;QACtC,wFAAwF;QACxF,yBAAyB;QACzB,iGAAiG;QACjG,8FAA8F;QAC9F,8FAA8F;QAC9F,wFAAwF;QACxF,4FAA4F;QAC5F,6FAA6F;QAC7F,4FAA4F;QAC5F,+FAA+F;QAC/F,4CAA4C;QAC5C,kGAAkG;QAClG,oDAAoD;IACtD,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,6EAA6E;oBAC7E,yDAAyD;aAC5D;SACF;QACD,QAAQ,EAAE,CAAC,eAAe,CAAC;QAC3B,qEAAqE;QACrE,6EAA6E;QAC7E,uBAAuB;QACvB,oBAAoB,EAAE,KAAK;KAC5B;IAED,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO;QACrB,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC,CAAC;QAE3E,MAAM,GAAG,GAAG,2BAA2B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAExD,MAAM,IAAI,GAAG,MAAM,aAAa,CAC9B,GAAG,EACH,wBAAwB,kBAAkB,CAAC,YAAY,CAAC,+BAA+B,EACvF,EAAE,EACF,OAAO,CAAC,KAAK,CACd,CAAC;QAEF,2EAA2E;QAC3E,yEAAyE;QACzE,2EAA2E;QAC3E,2EAA2E;QAC3E,0CAA0C;QAC1C,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACnC,UAAU,EAAE,IAAI;SACjB,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,uCAAuC,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getJsonObject,
|
|
1
|
+
import { getJsonObject, requireUserOrAgentApiConfig } from "../support/specguard-api.js";
|
|
2
2
|
import { requireString } from "./args.js";
|
|
3
3
|
/**
|
|
4
4
|
* `GET /api/v1/repositories/:repository_id/agent_keys` as a tool — shipped in
|
|
@@ -51,8 +51,16 @@ const listRepositoryAgentKeys = {
|
|
|
51
51
|
"Authorization is the `keys_manage` capability — a caller without it is refused 403 in " +
|
|
52
52
|
"SpecGuard's own words. " +
|
|
53
53
|
"Takes `repository_id` (the numeric id `list_repositories` reports, not the `org/repo` handle). " +
|
|
54
|
-
"
|
|
55
|
-
"
|
|
54
|
+
"It authenticates with EITHER of this server's two key-administration credentials, whichever " +
|
|
55
|
+
"is set: SPECGUARD_AGENT_API_KEY (an sga_… key — the call then reaches only the repositories " +
|
|
56
|
+
"granted onto that key at mint time, and only where the grant carries `keys.manage`; a " +
|
|
57
|
+
"repository outside that set answers 404 in SpecGuard's own words, never a probe here — an " +
|
|
58
|
+
"agent credential administering the keys it was granted needs no person's `sgu_` key to do " +
|
|
59
|
+
"it) and, when that is not set, SPECGUARD_USER_API_KEY (an sgu_… key, the same credential the " +
|
|
60
|
+
"other key-administration tools read). With both set the agent key wins, so the answer stays " +
|
|
61
|
+
"inside the same set `list_repositories` reports. " +
|
|
62
|
+
"Either way it is a DIFFERENT credential from the sgk_… repository key `get_repository_overview` " +
|
|
63
|
+
"uses; SpecGuard refuses each in the other's place.",
|
|
56
64
|
inputSchema: {
|
|
57
65
|
type: "object",
|
|
58
66
|
properties: {
|
|
@@ -70,7 +78,7 @@ const listRepositoryAgentKeys = {
|
|
|
70
78
|
},
|
|
71
79
|
async run(args, context) {
|
|
72
80
|
const repositoryId = requireString(args["repository_id"], "repository_id");
|
|
73
|
-
const api =
|
|
81
|
+
const api = requireUserOrAgentApiConfig(context.config);
|
|
74
82
|
const body = await getJsonObject(api, `/api/v1/repositories/${encodeURIComponent(repositoryId)}/agent_keys`, {}, context.fetch);
|
|
75
83
|
// Passed through unreshaped, the standing rule (`types.ts`: "A thin client
|
|
76
84
|
// that reshapes its upstream is not thin") — the rows are the controller's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-repository-agent-keys.js","sourceRoot":"","sources":["../../../src/tools/list-repository-agent-keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"list-repository-agent-keys.js","sourceRoot":"","sources":["../../../src/tools/list-repository-agent-keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,uBAAuB,GAAmB;IAC9C,IAAI,EAAE,4BAA4B;IAClC,KAAK,EAAE,4BAA4B;IACnC,WAAW,EACT,4FAA4F;QAC5F,8FAA8F;QAC9F,0EAA0E;QAC1E,+FAA+F;QAC/F,2FAA2F;QAC3F,sBAAsB;QACtB,+FAA+F;QAC/F,wFAAwF;QACxF,8FAA8F;QAC9F,sCAAsC;QACtC,wFAAwF;QACxF,yBAAyB;QACzB,iGAAiG;QACjG,8FAA8F;QAC9F,8FAA8F;QAC9F,wFAAwF;QACxF,4FAA4F;QAC5F,4FAA4F;QAC5F,+FAA+F;QAC/F,8FAA8F;QAC9F,mDAAmD;QACnD,kGAAkG;QAClG,oDAAoD;IACtD,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,gFAAgF;oBAChF,qEAAqE;aACxE;SACF;QACD,QAAQ,EAAE,CAAC,eAAe,CAAC;QAC3B,qEAAqE;QACrE,6EAA6E;QAC7E,uBAAuB;QACvB,oBAAoB,EAAE,KAAK;KAC5B;IAED,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO;QACrB,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC,CAAC;QAE3E,MAAM,GAAG,GAAG,2BAA2B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAExD,MAAM,IAAI,GAAG,MAAM,aAAa,CAC9B,GAAG,EACH,wBAAwB,kBAAkB,CAAC,YAAY,CAAC,aAAa,EACrE,EAAE,EACF,OAAO,CAAC,KAAK,CACd,CAAC;QAEF,2EAA2E;QAC3E,2EAA2E;QAC3E,0EAA0E;QAC1E,mCAAmC;QACnC,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACnC,UAAU,EAAE,IAAI;SACjB,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getJsonObject,
|
|
1
|
+
import { getJsonObject, requireUserOrAgentApiConfig } from "../support/specguard-api.js";
|
|
2
2
|
import { requireString } from "./args.js";
|
|
3
3
|
/**
|
|
4
4
|
* `GET /api/v1/repositories/:repository_id/members` as a tool — shipped in the
|
|
@@ -46,9 +46,15 @@ const listRepositoryMembers = {
|
|
|
46
46
|
"`members.manage` is refused 403 in SpecGuard's own words. " +
|
|
47
47
|
"Takes `repository_id` — the numeric id `list_repositories` reports, not the `org/repo` " +
|
|
48
48
|
"handle. " +
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"`
|
|
49
|
+
"It authenticates with EITHER of this server's two member-administration credentials, whichever " +
|
|
50
|
+
"is set: SPECGUARD_AGENT_API_KEY (an sga_… key — the call then reaches only the repositories " +
|
|
51
|
+
"granted onto that key at mint time, and only where the grant carries `members.manage`; a " +
|
|
52
|
+
"repository outside that set answers 404 in SpecGuard's own words, never a probe here) and, " +
|
|
53
|
+
"when that is not set, SPECGUARD_USER_API_KEY (an sgu_… key — a PERSON key, which " +
|
|
54
|
+
"`list_repositories` also accepts but does not require). With both set the agent key wins, so " +
|
|
55
|
+
"the answer stays inside the same set `list_repositories` reports. " +
|
|
56
|
+
"Either way it is a DIFFERENT credential from the sgk_… repository key `get_repository_overview` " +
|
|
57
|
+
"uses; SpecGuard refuses each in the other's place.",
|
|
52
58
|
inputSchema: {
|
|
53
59
|
type: "object",
|
|
54
60
|
properties: {
|
|
@@ -66,7 +72,7 @@ const listRepositoryMembers = {
|
|
|
66
72
|
},
|
|
67
73
|
async run(args, context) {
|
|
68
74
|
const repositoryId = requireString(args["repository_id"], "repository_id");
|
|
69
|
-
const api =
|
|
75
|
+
const api = requireUserOrAgentApiConfig(context.config);
|
|
70
76
|
const members = await getJsonObject(api, `/api/v1/repositories/${encodeURIComponent(repositoryId)}/members`, {}, context.fetch);
|
|
71
77
|
// Passed through unreshaped, the standing rule (`types.ts`: "A thin client
|
|
72
78
|
// that reshapes its upstream is not thin") — five fields per row, four of
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-repository-members.js","sourceRoot":"","sources":["../../../src/tools/list-repository-members.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"list-repository-members.js","sourceRoot":"","sources":["../../../src/tools/list-repository-members.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,qBAAqB,GAAmB;IAC5C,IAAI,EAAE,yBAAyB;IAC/B,KAAK,EAAE,yBAAyB;IAChC,WAAW,EACT,0FAA0F;QAC1F,6FAA6F;QAC7F,iGAAiG;QACjG,2FAA2F;QAC3F,2FAA2F;QAC3F,4DAA4D;QAC5D,wFAAwF;QACxF,4FAA4F;QAC5F,4DAA4D;QAC5D,yFAAyF;QACzF,UAAU;QACV,iGAAiG;QACjG,8FAA8F;QAC9F,2FAA2F;QAC3F,6FAA6F;QAC7F,mFAAmF;QACnF,+FAA+F;QAC/F,oEAAoE;QACpE,kGAAkG;QAClG,oDAAoD;IACtD,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,6EAA6E;oBAC7E,qEAAqE;aACxE;SACF;QACD,QAAQ,EAAE,CAAC,eAAe,CAAC;QAC3B,qEAAqE;QACrE,6EAA6E;QAC7E,uBAAuB;QACvB,oBAAoB,EAAE,KAAK;KAC5B;IAED,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO;QACrB,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC,CAAC;QAE3E,MAAM,GAAG,GAAG,2BAA2B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAExD,MAAM,OAAO,GAAG,MAAM,aAAa,CACjC,GAAG,EACH,wBAAwB,kBAAkB,CAAC,YAAY,CAAC,UAAU,EAClE,EAAE,EACF,OAAO,CAAC,KAAK,CACd,CAAC;QAEF,2EAA2E;QAC3E,0EAA0E;QAC1E,wEAAwE;QACxE,oDAAoD;QACpD,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACtC,UAAU,EAAE,OAAO;SACpB,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deleteJson,
|
|
1
|
+
import { deleteJson, requireUserOrAgentApiConfig } from "../support/specguard-api.js";
|
|
2
2
|
import { requireString } from "./args.js";
|
|
3
3
|
/**
|
|
4
4
|
* `DELETE /api/v1/repositories/:repository_id/members/:id` as a tool — shipped
|
|
@@ -52,8 +52,15 @@ const removeRepositoryMember = {
|
|
|
52
52
|
"SpecGuard's own words. A 204 means the membership is revoked. " +
|
|
53
53
|
"Takes `repository_id` — the numeric id `list_repositories` reports, not the `org/repo` " +
|
|
54
54
|
"handle. " +
|
|
55
|
-
"
|
|
56
|
-
"
|
|
55
|
+
"It authenticates with EITHER of this server's two member-administration credentials, whichever " +
|
|
56
|
+
"is set: SPECGUARD_AGENT_API_KEY (an sga_… key — the call then reaches only the repositories " +
|
|
57
|
+
"granted onto that key at mint time, and only where the grant carries `members.manage`; a " +
|
|
58
|
+
"repository outside that set answers 404 in SpecGuard's own words, never a probe here) and, " +
|
|
59
|
+
"when that is not set, SPECGUARD_USER_API_KEY (an sgu_… key, the same credential " +
|
|
60
|
+
"`add_repository` writes with). With both set the agent key wins, so the revoke answers inside " +
|
|
61
|
+
"the same set `list_repositories` reports. " +
|
|
62
|
+
"Either way it is a DIFFERENT credential from the sgk_… repository key `get_repository_overview` " +
|
|
63
|
+
"uses.",
|
|
57
64
|
inputSchema: {
|
|
58
65
|
type: "object",
|
|
59
66
|
properties: {
|
|
@@ -81,7 +88,7 @@ const removeRepositoryMember = {
|
|
|
81
88
|
async run(args, context) {
|
|
82
89
|
const repositoryId = requireString(args["repository_id"], "repository_id");
|
|
83
90
|
const memberId = requireString(args["member_id"], "member_id");
|
|
84
|
-
const api =
|
|
91
|
+
const api = requireUserOrAgentApiConfig(context.config);
|
|
85
92
|
const body = await deleteJson(api, `/api/v1/repositories/${encodeURIComponent(repositoryId)}/members/${encodeURIComponent(memberId)}`, context.fetch);
|
|
86
93
|
// 204 with no body — the tool's own words, because the deployment's whole
|
|
87
94
|
// answer was "no content". The keys asymmetry is restated here because the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remove-repository-member.js","sourceRoot":"","sources":["../../../src/tools/remove-repository-member.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"remove-repository-member.js","sourceRoot":"","sources":["../../../src/tools/remove-repository-member.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,sBAAsB,GAAmB;IAC7C,IAAI,EAAE,0BAA0B;IAChC,KAAK,EAAE,0BAA0B;IACjC,WAAW,EACT,sFAAsF;QACtF,kFAAkF;QAClF,uFAAuF;QACvF,mCAAmC;QACnC,yFAAyF;QACzF,uFAAuF;QACvF,uDAAuD;QACvD,yFAAyF;QACzF,2FAA2F;QAC3F,4FAA4F;QAC5F,iEAAiE;QACjE,2FAA2F;QAC3F,uFAAuF;QACvF,0FAA0F;QAC1F,4FAA4F;QAC5F,6FAA6F;QAC7F,4FAA4F;QAC5F,YAAY;QACZ,2FAA2F;QAC3F,gEAAgE;QAChE,yFAAyF;QACzF,UAAU;QACV,iGAAiG;QACjG,8FAA8F;QAC9F,2FAA2F;QAC3F,6FAA6F;QAC7F,kFAAkF;QAClF,gGAAgG;QAChG,4CAA4C;QAC5C,kGAAkG;QAClG,OAAO;IACT,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,iFAAiF;oBACjF,qEAAqE;aACxE;YACD,SAAS,EAAE;gBACT,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,8EAA8E;oBAC9E,kFAAkF;oBAClF,sEAAsE;oBACtE,iFAAiF;oBACjF,8EAA8E;oBAC9E,iBAAiB;aACpB;SACF;QACD,QAAQ,EAAE,CAAC,eAAe,EAAE,WAAW,CAAC;QACxC,4EAA4E;QAC5E,uEAAuE;QACvE,gEAAgE;QAChE,oBAAoB,EAAE,KAAK;KAC5B;IAED,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO;QACrB,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC,CAAC;QAC3E,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC;QAE/D,MAAM,GAAG,GAAG,2BAA2B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAExD,MAAM,IAAI,GAAG,MAAM,UAAU,CAC3B,GAAG,EACH,wBAAwB,kBAAkB,CAAC,YAAY,CAAC,YAAY,kBAAkB,CAAC,QAAQ,CAAC,EAAE,EAClG,OAAO,CAAC,KAAK,CACd,CAAC;QAEF,0EAA0E;QAC1E,2EAA2E;QAC3E,+DAA+D;QAC/D,OAAO;YACL,IAAI,EACF,IAAI,KAAK,EAAE;gBACT,CAAC,CAAC,cAAc,QAAQ,uDAAuD;oBAC7E,gEAAgE;oBAChE,kDAAkD;gBACpD,CAAC,CAAC,IAAI;YACV,UAAU,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;SAChF,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -35,10 +35,16 @@ import type { ToolDefinition } from "./types.js";
|
|
|
35
35
|
* description says so because it is the one answer an agent is most likely to
|
|
36
36
|
* mispredict.
|
|
37
37
|
*
|
|
38
|
-
* == The 200 body is the
|
|
38
|
+
* == The 200 body is the receipt shape — WITHOUT the list's `latest_run`
|
|
39
39
|
*
|
|
40
40
|
* `{repository: serialize(...)}` — the same serializer `list_repositories`
|
|
41
|
-
* serves, so the response needs no reshaping and gets none.
|
|
41
|
+
* serves, so the response needs no reshaping and gets none. But the entry is
|
|
42
|
+
* a rename receipt, not a list entry: it carries the identity fields and
|
|
43
|
+
* `delivery_health`, and `latest_run` is ABSENT — an absent key, never a
|
|
44
|
+
* null — deliberately: naming `latest_run` in a receipt would assert "CI has
|
|
45
|
+
* never reported" about a repository the endpoint knows was untouched by the
|
|
46
|
+
* rename. `list_repositories` is the only surface of the two that serves a
|
|
47
|
+
* run summary (present-and-null there when CI has never reported).
|
|
42
48
|
*/
|
|
43
49
|
declare const renameRepository: ToolDefinition;
|
|
44
50
|
export default renameRepository;
|
|
@@ -36,10 +36,16 @@ import { requireString } from "./args.js";
|
|
|
36
36
|
* description says so because it is the one answer an agent is most likely to
|
|
37
37
|
* mispredict.
|
|
38
38
|
*
|
|
39
|
-
* == The 200 body is the
|
|
39
|
+
* == The 200 body is the receipt shape — WITHOUT the list's `latest_run`
|
|
40
40
|
*
|
|
41
41
|
* `{repository: serialize(...)}` — the same serializer `list_repositories`
|
|
42
|
-
* serves, so the response needs no reshaping and gets none.
|
|
42
|
+
* serves, so the response needs no reshaping and gets none. But the entry is
|
|
43
|
+
* a rename receipt, not a list entry: it carries the identity fields and
|
|
44
|
+
* `delivery_health`, and `latest_run` is ABSENT — an absent key, never a
|
|
45
|
+
* null — deliberately: naming `latest_run` in a receipt would assert "CI has
|
|
46
|
+
* never reported" about a repository the endpoint knows was untouched by the
|
|
47
|
+
* rename. `list_repositories` is the only surface of the two that serves a
|
|
48
|
+
* run summary (present-and-null there when CI has never reported).
|
|
43
49
|
*/
|
|
44
50
|
const renameRepository = {
|
|
45
51
|
name: "rename_repository",
|
|
@@ -53,8 +59,11 @@ const renameRepository = {
|
|
|
53
59
|
"redeems a browser-issued grant valid for 7 days; a nil or stale one is refused 403 in " +
|
|
54
60
|
"SpecGuard's own words, and that sentence names the fix (re-grant via the browser). " +
|
|
55
61
|
"A name another repository already holds is refused 400 — `taken`, not 409 — with " +
|
|
56
|
-
"SpecGuard's own sentence. The 200 body is `{repository: …}`
|
|
57
|
-
"`list_repositories`
|
|
62
|
+
"SpecGuard's own sentence. The 200 body is `{repository: …}` — served by the same serializer " +
|
|
63
|
+
"`list_repositories` uses, but a rename receipt, not a list entry: it carries the identity " +
|
|
64
|
+
"fields and `delivery_health`, and `latest_run` is absent entirely (an absent key, never a " +
|
|
65
|
+
"null), deliberately, so the receipt claims nothing about the repository's CI state — " +
|
|
66
|
+
"`list_repositories` is the tool to ask for a run summary. " +
|
|
58
67
|
"Takes `repository_id` — the numeric id `add_repository` returns and `list_repositories` " +
|
|
59
68
|
"reports, not the `org/repo` handle — and `github_full_name`, the new `org/repo` name. " +
|
|
60
69
|
"Needs SPECGUARD_USER_API_KEY (an sgu_… key), the same credential `add_repository` " +
|
|
@@ -87,8 +96,9 @@ const renameRepository = {
|
|
|
87
96
|
const githubFullName = requireString(args["github_full_name"], "github_full_name");
|
|
88
97
|
const api = requireUserApiConfig(context.config);
|
|
89
98
|
const updated = await patchJsonObject(api, `/api/v1/repositories/${encodeURIComponent(repositoryId)}`, { github_full_name: githubFullName }, context.fetch);
|
|
90
|
-
// Unreshaped, the standing rule — the 200 body (`{repository: serialize}
|
|
91
|
-
// the
|
|
99
|
+
// Unreshaped, the standing rule — the 200 body (`{repository: serialize}`,
|
|
100
|
+
// the receipt shape: the identity fields and `delivery_health`, WITHOUT the
|
|
101
|
+
// list's `latest_run`, absent here — never null) is this verb's whole answer.
|
|
92
102
|
return {
|
|
93
103
|
text: JSON.stringify(updated, null, 2),
|
|
94
104
|
structured: updated,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rename-repository.js","sourceRoot":"","sources":["../../../src/tools/rename-repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C
|
|
1
|
+
{"version":3,"file":"rename-repository.js","sourceRoot":"","sources":["../../../src/tools/rename-repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAM,gBAAgB,GAAmB;IACvC,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,mBAAmB;IAC1B,WAAW,EACT,4FAA4F;QAC5F,6FAA6F;QAC7F,2FAA2F;QAC3F,eAAe;QACf,wFAAwF;QACxF,uFAAuF;QACvF,wFAAwF;QACxF,qFAAqF;QACrF,mFAAmF;QACnF,8FAA8F;QAC9F,4FAA4F;QAC5F,4FAA4F;QAC5F,uFAAuF;QACvF,4DAA4D;QAC5D,0FAA0F;QAC1F,wFAAwF;QACxF,oFAAoF;QACpF,+FAA+F;IACjG,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,mFAAmF;oBACnF,sFAAsF;oBACtF,oDAAoD;aACvD;YACD,gBAAgB,EAAE;gBAChB,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,oFAAoF;oBACpF,kFAAkF;oBAClF,wBAAwB;aAC3B;SACF;QACD,QAAQ,EAAE,CAAC,eAAe,EAAE,kBAAkB,CAAC;QAC/C,qEAAqE;QACrE,yEAAyE;QACzE,wEAAwE;QACxE,+BAA+B;QAC/B,oBAAoB,EAAE,KAAK;KAC5B;IAED,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO;QACrB,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC,CAAC;QAC3E,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC,CAAC;QAEnF,MAAM,GAAG,GAAG,oBAAoB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAEjD,MAAM,OAAO,GAAG,MAAM,eAAe,CACnC,GAAG,EACH,wBAAwB,kBAAkB,CAAC,YAAY,CAAC,EAAE,EAC1D,EAAE,gBAAgB,EAAE,cAAc,EAAE,EACpC,OAAO,CAAC,KAAK,CACd,CAAC;QAEF,2EAA2E;QAC3E,4EAA4E;QAC5E,8EAA8E;QAC9E,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACtC,UAAU,EAAE,OAAO;SACpB,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deleteJsonObject,
|
|
1
|
+
import { deleteJsonObject, requireUserOrAgentApiConfig } from "../support/specguard-api.js";
|
|
2
2
|
import { requireString } from "./args.js";
|
|
3
3
|
/**
|
|
4
4
|
* `DELETE /api/v1/repositories/:repository_id/agent_keys/:id` as a tool —
|
|
@@ -61,8 +61,16 @@ const revokeRepositoryAgentKey = {
|
|
|
61
61
|
"Authorization is the `keys_manage` capability — a caller without it is refused 403 in " +
|
|
62
62
|
"SpecGuard's own words. " +
|
|
63
63
|
"Takes `repository_id` (the numeric id `list_repositories` reports) and `key_id`. " +
|
|
64
|
-
"
|
|
65
|
-
"
|
|
64
|
+
"It authenticates with EITHER of this server's two key-administration credentials, whichever " +
|
|
65
|
+
"is set: SPECGUARD_AGENT_API_KEY (an sga_… key — the call then reaches only the repositories " +
|
|
66
|
+
"granted onto that key at mint time, and only where the grant carries `keys.manage`; a " +
|
|
67
|
+
"repository outside that set answers 404 in SpecGuard's own words, never a probe here — an " +
|
|
68
|
+
"agent credential revoking one of its own kind needs no person's `sgu_` key to do it) and, " +
|
|
69
|
+
"when that is not set, SPECGUARD_USER_API_KEY (an sgu_… key, the same credential the other " +
|
|
70
|
+
"key-administration tools read). With both set the agent key wins, so the cut answers inside " +
|
|
71
|
+
"the same set `list_repositories` reports. " +
|
|
72
|
+
"Either way it is a DIFFERENT credential from the sgk_… repository key `get_repository_overview` " +
|
|
73
|
+
"uses; SpecGuard refuses each in the other's place.",
|
|
66
74
|
inputSchema: {
|
|
67
75
|
type: "object",
|
|
68
76
|
properties: {
|
|
@@ -89,7 +97,7 @@ const revokeRepositoryAgentKey = {
|
|
|
89
97
|
async run(args, context) {
|
|
90
98
|
const repositoryId = requireString(args["repository_id"], "repository_id");
|
|
91
99
|
const keyId = requireString(args["key_id"], "key_id");
|
|
92
|
-
const api =
|
|
100
|
+
const api = requireUserOrAgentApiConfig(context.config);
|
|
93
101
|
// The 200 disclosure body, passed through unreshaped in both halves — the
|
|
94
102
|
// deployment already wrote the confirmation (the stored set, count first),
|
|
95
103
|
// and this is the API's substitute for the web confirm dialog.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revoke-repository-agent-key.js","sourceRoot":"","sources":["../../../src/tools/revoke-repository-agent-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"revoke-repository-agent-key.js","sourceRoot":"","sources":["../../../src/tools/revoke-repository-agent-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC5F,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,wBAAwB,GAAmB;IAC/C,IAAI,EAAE,6BAA6B;IACnC,KAAK,EAAE,6BAA6B;IACpC,WAAW,EACT,6FAA6F;QAC7F,8FAA8F;QAC9F,6FAA6F;QAC7F,yFAAyF;QACzF,kCAAkC;QAClC,uFAAuF;QACvF,uEAAuE;QACvE,4FAA4F;QAC5F,wFAAwF;QACxF,wFAAwF;QACxF,oFAAoF;QACpF,0FAA0F;QAC1F,wEAAwE;QACxE,wFAAwF;QACxF,yBAAyB;QACzB,mFAAmF;QACnF,8FAA8F;QAC9F,8FAA8F;QAC9F,wFAAwF;QACxF,4FAA4F;QAC5F,4FAA4F;QAC5F,4FAA4F;QAC5F,8FAA8F;QAC9F,4CAA4C;QAC5C,kGAAkG;QAClG,oDAAoD;IACtD,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,qFAAqF;oBACrF,sFAAsF;oBACtF,8EAA8E;aACjF;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,iFAAiF;oBACjF,qFAAqF;oBACrF,mFAAmF;oBACnF,0BAA0B;aAC7B;SACF;QACD,QAAQ,EAAE,CAAC,eAAe,EAAE,QAAQ,CAAC;QACrC,4EAA4E;QAC5E,uEAAuE;QACvE,yDAAyD;QACzD,oBAAoB,EAAE,KAAK;KAC5B;IAED,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO;QACrB,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC,CAAC;QAC3E,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;QAEtD,MAAM,GAAG,GAAG,2BAA2B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAExD,0EAA0E;QAC1E,2EAA2E;QAC3E,+DAA+D;QAC/D,MAAM,UAAU,GAAG,MAAM,gBAAgB,CACvC,GAAG,EACH,wBAAwB,kBAAkB,CAAC,YAAY,CAAC,eAAe,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAClG,OAAO,CAAC,KAAK,CACd,CAAC;QAEF,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;YACzC,UAAU,EAAE,UAAU;SACvB,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,wBAAwB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deleteJson,
|
|
1
|
+
import { deleteJson, requireUserOrAgentApiConfig } from "../support/specguard-api.js";
|
|
2
2
|
import { requireString } from "./args.js";
|
|
3
3
|
/**
|
|
4
4
|
* `DELETE /api/v1/repositories/:repository_id/api_keys/:id` as a tool —
|
|
@@ -42,9 +42,15 @@ const revokeRepositoryApiKey = {
|
|
|
42
42
|
"403 in SpecGuard's own words. A 204 means the key is revoked. " +
|
|
43
43
|
"Takes `repository_id` (the numeric id `list_repositories` reports) and `key_id` " +
|
|
44
44
|
"(the id from `add_repository`'s or `create_repository_api_key`'s response). " +
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"`
|
|
45
|
+
"It authenticates with EITHER of this server's two key-administration credentials, whichever " +
|
|
46
|
+
"is set: SPECGUARD_AGENT_API_KEY (an sga_… key — the call then reaches only the repositories " +
|
|
47
|
+
"granted onto that key at mint time, and only where the grant carries `keys.manage`; a " +
|
|
48
|
+
"repository outside that set answers 404 in SpecGuard's own words, never a probe here) and, " +
|
|
49
|
+
"when that is not set, SPECGUARD_USER_API_KEY (an sgu_… key, the same credential " +
|
|
50
|
+
"`add_repository` writes with). With both set the agent key wins, so the revoke answers inside " +
|
|
51
|
+
"the same set `list_repositories` reports. " +
|
|
52
|
+
"Either way it is a DIFFERENT credential from the sgk_… repository key " +
|
|
53
|
+
"`get_repository_overview` uses; SpecGuard refuses each in the other's place.",
|
|
48
54
|
inputSchema: {
|
|
49
55
|
type: "object",
|
|
50
56
|
properties: {
|
|
@@ -69,7 +75,7 @@ const revokeRepositoryApiKey = {
|
|
|
69
75
|
async run(args, context) {
|
|
70
76
|
const repositoryId = requireString(args["repository_id"], "repository_id");
|
|
71
77
|
const keyId = requireString(args["key_id"], "key_id");
|
|
72
|
-
const api =
|
|
78
|
+
const api = requireUserOrAgentApiConfig(context.config);
|
|
73
79
|
const body = await deleteJson(api, `/api/v1/repositories/${encodeURIComponent(repositoryId)}/api_keys/${encodeURIComponent(keyId)}`, context.fetch);
|
|
74
80
|
// 204 with no body — the tool's own words, because the deployment's whole
|
|
75
81
|
// answer was "no content".
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revoke-repository-api-key.js","sourceRoot":"","sources":["../../../src/tools/revoke-repository-api-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"revoke-repository-api-key.js","sourceRoot":"","sources":["../../../src/tools/revoke-repository-api-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,sBAAsB,GAAmB;IAC7C,IAAI,EAAE,2BAA2B;IACjC,KAAK,EAAE,2BAA2B;IAClC,WAAW,EACT,iFAAiF;QACjF,4EAA4E;QAC5E,yCAAyC;QACzC,+EAA+E;QAC/E,8DAA8D;QAC9D,mFAAmF;QACnF,8EAA8E;QAC9E,kFAAkF;QAClF,wCAAwC;QACxC,iFAAiF;QACjF,gEAAgE;QAChE,kFAAkF;QAClF,8EAA8E;QAC9E,8FAA8F;QAC9F,8FAA8F;QAC9F,wFAAwF;QACxF,6FAA6F;QAC7F,kFAAkF;QAClF,gGAAgG;QAChG,4CAA4C;QAC5C,wEAAwE;QACxE,8EAA8E;IAChF,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,0EAA0E;oBAC1E,qEAAqE;aACxE;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,mEAAmE;oBACnE,uEAAuE;oBACvE,6EAA6E;aAChF;SACF;QACD,QAAQ,EAAE,CAAC,eAAe,EAAE,QAAQ,CAAC;QACrC,4EAA4E;QAC5E,uEAAuE;QACvE,yDAAyD;QACzD,oBAAoB,EAAE,KAAK;KAC5B;IAED,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO;QACrB,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC,CAAC;QAC3E,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;QAEtD,MAAM,GAAG,GAAG,2BAA2B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAExD,MAAM,IAAI,GAAG,MAAM,UAAU,CAC3B,GAAG,EACH,wBAAwB,kBAAkB,CAAC,YAAY,CAAC,aAAa,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAChG,OAAO,CAAC,KAAK,CACd,CAAC;QAEF,0EAA0E;QAC1E,2BAA2B;QAC3B,OAAO;YACL,IAAI,EACF,IAAI,KAAK,EAAE;gBACT,CAAC,CAAC,OAAO,KAAK,mEAAmE;gBACjF,CAAC,CAAC,IAAI;YACV,UAAU,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE;SAC1E,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { patchJsonObject,
|
|
1
|
+
import { patchJsonObject, requireUserOrAgentApiConfig } from "../support/specguard-api.js";
|
|
2
2
|
import { requireString, requireStringArray } from "./args.js";
|
|
3
3
|
/**
|
|
4
4
|
* `PATCH /api/v1/repositories/:repository_id/members/:id` as a tool — shipped
|
|
@@ -49,8 +49,17 @@ const updateRepositoryMemberPermissions = {
|
|
|
49
49
|
"SpecGuard's own words. " +
|
|
50
50
|
"Takes `repository_id` — the numeric id `list_repositories` reports, not the `org/repo` " +
|
|
51
51
|
"handle. " +
|
|
52
|
-
"
|
|
53
|
-
"
|
|
52
|
+
"It authenticates with EITHER of this server's two member-administration credentials, whichever " +
|
|
53
|
+
"is set: SPECGUARD_AGENT_API_KEY (an sga_… key — the call then reaches only the repositories " +
|
|
54
|
+
"granted onto that key at mint time, and only where the grant carries `members.manage`; a " +
|
|
55
|
+
"repository outside that set answers 404 in SpecGuard's own words, never a probe here) and, " +
|
|
56
|
+
"when that is not set, SPECGUARD_USER_API_KEY (an sgu_… key, the same credential " +
|
|
57
|
+
"`add_repository` writes with). With both set the agent key wins, so the edit answers inside " +
|
|
58
|
+
"the same set `list_repositories` reports. Under the agent credential the replacement set is " +
|
|
59
|
+
"bounded twice: the key cannot grant a permission it does not itself hold (SpecGuard answers " +
|
|
60
|
+
"400 naming the over-reach), and the re-stamped grantor is the key's owner. " +
|
|
61
|
+
"Either way it is a DIFFERENT credential from the sgk_… repository key `get_repository_overview` " +
|
|
62
|
+
"uses.",
|
|
54
63
|
inputSchema: {
|
|
55
64
|
type: "object",
|
|
56
65
|
properties: {
|
|
@@ -90,7 +99,7 @@ const updateRepositoryMemberPermissions = {
|
|
|
90
99
|
// caught here — before a write — rather than persisted as a member holding
|
|
91
100
|
// nothing.
|
|
92
101
|
const permissions = requireStringArray(args["permissions"], "permissions");
|
|
93
|
-
const api =
|
|
102
|
+
const api = requireUserOrAgentApiConfig(context.config);
|
|
94
103
|
const updated = await patchJsonObject(api, `/api/v1/repositories/${encodeURIComponent(repositoryId)}/members/${encodeURIComponent(memberId)}`, { permissions }, context.fetch);
|
|
95
104
|
// Unreshaped, the standing rule — the 200 body is this verb's whole answer.
|
|
96
105
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-repository-member-permissions.js","sourceRoot":"","sources":["../../../src/tools/update-repository-member-permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"update-repository-member-permissions.js","sourceRoot":"","sources":["../../../src/tools/update-repository-member-permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG9D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,iCAAiC,GAAmB;IACxD,IAAI,EAAE,sCAAsC;IAC5C,KAAK,EAAE,sCAAsC;IAC7C,WAAW,EACT,yFAAyF;QACzF,0FAA0F;QAC1F,8EAA8E;QAC9E,0BAA0B;QAC1B,wFAAwF;QACxF,sFAAsF;QACtF,2FAA2F;QAC3F,6CAA6C;QAC7C,2FAA2F;QAC3F,4FAA4F;QAC5F,2FAA2F;QAC3F,2FAA2F;QAC3F,4FAA4F;QAC5F,yEAAyE;QACzE,2FAA2F;QAC3F,yBAAyB;QACzB,yFAAyF;QACzF,UAAU;QACV,iGAAiG;QACjG,8FAA8F;QAC9F,2FAA2F;QAC3F,6FAA6F;QAC7F,kFAAkF;QAClF,8FAA8F;QAC9F,8FAA8F;QAC9F,8FAA8F;QAC9F,6EAA6E;QAC7E,kGAAkG;QAClG,OAAO;IACT,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,iFAAiF;oBACjF,qEAAqE;aACxE;YACD,SAAS,EAAE;gBACT,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,mFAAmF;oBACnF,oFAAoF;oBACpF,qFAAqF;oBACrF,oFAAoF;oBACpF,oDAAoD;aACvD;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,WAAW,EACT,kFAAkF;oBAClF,mFAAmF;oBACnF,0CAA0C;aAC7C;SACF;QACD,QAAQ,EAAE,CAAC,eAAe,EAAE,WAAW,EAAE,aAAa,CAAC;QACvD,qEAAqE;QACrE,yEAAyE;QACzE,uEAAuE;QACvE,sBAAsB;QACtB,oBAAoB,EAAE,KAAK;KAC5B;IAED,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO;QACrB,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC,CAAC;QAC3E,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC;QAC/D,0EAA0E;QAC1E,4EAA4E;QAC5E,2EAA2E;QAC3E,WAAW;QACX,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC,CAAC;QAE3E,MAAM,GAAG,GAAG,2BAA2B,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAExD,MAAM,OAAO,GAAG,MAAM,eAAe,CACnC,GAAG,EACH,wBAAwB,kBAAkB,CAAC,YAAY,CAAC,YAAY,kBAAkB,CAAC,QAAQ,CAAC,EAAE,EAClG,EAAE,WAAW,EAAE,EACf,OAAO,CAAC,KAAK,CACd,CAAC;QAEF,4EAA4E;QAC5E,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACtC,UAAU,EAAE,OAAO;SACpB,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,iCAAiC,CAAC"}
|