Skip to content

Commit c2c01ad

Browse files
authored
Merge pull request OneIdentity#75 from petrsnd/feature/agent-skills
Agent skill system for authoring custom platform scripts
2 parents 77bc622 + bfd9a93 commit c2c01ad

21 files changed

Lines changed: 4018 additions & 0 deletions

File tree

.agents/CONVENTIONS.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Notation conventions
2+
3+
Agent-facing material in this repo distinguishes three shapes so an agent never has to guess whether a token is a cmdlet parameter, an API field, or a transport-agnostic idea.
4+
5+
- **PowerShell** — backtick the literal as it appears in `Get-Help <Cmdlet> -Full`. Switches stand alone; valued parameters use a space before the value.
6+
- `` `-ExtendedLogging` `` (switch), `` `-TaskId <GUID>` `` (valued), `` `Connect-Safeguard -DeviceCode` `` (cmdlet + switch).
7+
- **API / JSON** — backtick a PascalCase field as `Field: value`, mirroring the transfer-object shape SPP emits and accepts.
8+
- `` `ExtendedLogs: true` ``, `` `OperationType: CheckPassword` ``.
9+
- **Concept (transport-agnostic)** — plain English, no backticks. Use this in orchestration prose where the agent should not yet be biased toward PS or API.
10+
- "with extended logging enabled", "trigger the affected operation".
11+
12+
Rule of thumb: `AGENTS.md` speaks **concept**. The skills speak **PowerShell** (e.g., `safeguard-ps-operations`) or **API** with backticks. When a skill bridges them, it shows both forms side by side.
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://raw.githubusercontent.com/petrsnd/SafeguardCustomPlatform/main/.agents/schemas/evidence.schema.json",
4+
"title": "Custom Platform Probing Evidence",
5+
"description": "Internal agent contract. The evidence artifact produced by the target-probing skill and consumed by strategy-selection and script-authoring. Distinct from the human-facing platform-script schema in schema/. This is v0 — fields marked TODO require a real probing run to lock down their shape; do not invent values.",
6+
"type": "object",
7+
"required": [
8+
"schemaVersion",
9+
"protocol",
10+
"target",
11+
"serviceAccount",
12+
"probeRun"
13+
],
14+
"additionalProperties": false,
15+
"properties": {
16+
"schemaVersion": {
17+
"type": "string",
18+
"description": "Version of this evidence schema. Bumped when the contract changes.",
19+
"const": "0.1"
20+
},
21+
"protocol": {
22+
"type": "string",
23+
"description": "Transport protocol of the target. SSH and HTTP only — telnet is out of scope for the agent skill system.",
24+
"enum": ["ssh", "http"]
25+
},
26+
"target": {
27+
"type": "object",
28+
"description": "Identification of the target system the probes ran against.",
29+
"required": ["host"],
30+
"additionalProperties": false,
31+
"properties": {
32+
"host": {
33+
"type": "string",
34+
"description": "Hostname or IP of the target. No credentials."
35+
},
36+
"port": {
37+
"type": "integer",
38+
"description": "TCP port. Optional; default depends on protocol."
39+
},
40+
"nonProductionAffirmed": {
41+
"type": "boolean",
42+
"description": "Whether the operator has affirmed the target is non-production. The probe-safety contract requires this to be true before any probe runs."
43+
}
44+
}
45+
},
46+
"serviceAccount": {
47+
"type": "object",
48+
"description": "Service-account identification used by probes to authenticate to the target. Secrets MUST NOT appear here — name and credential kind only.",
49+
"required": ["accountName"],
50+
"additionalProperties": false,
51+
"properties": {
52+
"accountName": {
53+
"type": "string",
54+
"description": "Username/account identifier used for probing. The secret itself is never recorded in evidence."
55+
},
56+
"credentialKind": {
57+
"type": "string",
58+
"description": "What kind of credential the service account uses. Sourced from operator declaration; not inferred.",
59+
"enum": ["password", "ssh-key", "api-key", "bearer-token", "unknown"]
60+
}
61+
}
62+
},
63+
"probeRun": {
64+
"type": "object",
65+
"description": "Metadata about the probing session itself.",
66+
"required": ["startedAt", "probes"],
67+
"additionalProperties": false,
68+
"properties": {
69+
"startedAt": {
70+
"type": "string",
71+
"format": "date-time",
72+
"description": "ISO-8601 UTC timestamp when probing began."
73+
},
74+
"endedAt": {
75+
"type": "string",
76+
"format": "date-time",
77+
"description": "ISO-8601 UTC timestamp when probing concluded. Optional while probing is in progress."
78+
},
79+
"operatorTool": {
80+
"type": "string",
81+
"description": "Identifier of the agent runtime that performed the probes (e.g., 'github-copilot-cli', 'claude-code'). For audit only."
82+
},
83+
"probes": {
84+
"type": "array",
85+
"description": "Ordered record of probes executed. Each entry is a single probe step. Read-only probes record observations; destructive probes additionally record the explicit per-probe consent given by the operator (see the probe-safety contract in target-probing/SKILL.md).",
86+
"items": {
87+
"$ref": "#/definitions/probeRecord"
88+
}
89+
},
90+
"haltedReason": {
91+
"type": "string",
92+
"description": "If probing stopped before completion, why. Examples: 'lockout-signal', 'throttle-signal', 'mfa-challenge', 'operator-stop', 'rate-limit-exceeded'.",
93+
"enum": [
94+
"completed",
95+
"lockout-signal",
96+
"throttle-signal",
97+
"mfa-challenge",
98+
"operator-stop",
99+
"rate-limit-exceeded",
100+
"operator-denied-destructive",
101+
"error"
102+
]
103+
}
104+
}
105+
},
106+
"sshFindings": {
107+
"$ref": "#/definitions/sshFindings",
108+
"description": "Findings produced by SSH probe playbooks. Present only when protocol == 'ssh'."
109+
},
110+
"httpFindings": {
111+
"$ref": "#/definitions/httpFindings",
112+
"description": "Findings produced by HTTP probe playbooks. Present only when protocol == 'http'."
113+
},
114+
"strategyHints": {
115+
"type": "object",
116+
"description": "Optional hints from the probing skill that strategy-selection may consider. Not authoritative — strategy-selection makes the final call.",
117+
"additionalProperties": false,
118+
"properties": {
119+
"preferredPattern": {
120+
"type": "string",
121+
"description": "If probing strongly suggests one of the four authoring patterns, name it here. Otherwise omit.",
122+
"enum": [
123+
"ssh-interactive",
124+
"ssh-batch",
125+
"http-api",
126+
"http-form-fill"
127+
]
128+
},
129+
"rationale": {
130+
"type": "string",
131+
"description": "Short, citation-style reason for the hint. Must reference a specific probe record, not be generic."
132+
}
133+
}
134+
}
135+
},
136+
"definitions": {
137+
"probeRecord": {
138+
"type": "object",
139+
"description": "A single probe step. Field shapes for 'observation' and 'destructiveDetails' are placeholders pending a real probing run; populated structures land in Phase 3 / Phase 5.",
140+
"required": ["id", "kind", "command", "result"],
141+
"additionalProperties": false,
142+
"properties": {
143+
"id": {
144+
"type": "string",
145+
"description": "Stable ID of the probe within this run. Used for back-references."
146+
},
147+
"kind": {
148+
"type": "string",
149+
"description": "Probe classification. Read-only probes never mutate target state.",
150+
"enum": ["read-only", "destructive"]
151+
},
152+
"category": {
153+
"type": "string",
154+
"description": "What the probe is investigating. SSH categories: prompt, batch-mode, sudo, password-change. HTTP categories: auth-scheme, login-form, cookie, api-discovery.",
155+
"enum": [
156+
"prompt",
157+
"batch-mode",
158+
"sudo",
159+
"password-change",
160+
"auth-scheme",
161+
"login-form",
162+
"cookie",
163+
"api-discovery",
164+
"other"
165+
]
166+
},
167+
"command": {
168+
"type": "string",
169+
"description": "The exact command or HTTP request line that was issued. No secrets — substitute placeholders for credentials."
170+
},
171+
"consent": {
172+
"type": "object",
173+
"description": "Required for destructive probes; absent for read-only probes.",
174+
"additionalProperties": false,
175+
"required": ["grantedAt"],
176+
"properties": {
177+
"grantedAt": {
178+
"type": "string",
179+
"format": "date-time",
180+
"description": "Timestamp the operator granted explicit per-probe consent."
181+
},
182+
"summaryShown": {
183+
"type": "string",
184+
"description": "The one-line 'what this will do, what could go wrong' summary that the operator approved."
185+
}
186+
}
187+
},
188+
"result": {
189+
"type": "string",
190+
"description": "Outcome of the probe.",
191+
"enum": ["ok", "failed", "skipped", "halted"]
192+
},
193+
"observation": {
194+
"description": "TODO: structured observation payload. Shape locked down in Phase 3 once the SSH and HTTP playbooks are authored against real targets. Free-form for now.",
195+
"type": "object",
196+
"additionalProperties": true
197+
},
198+
"errorSignature": {
199+
"type": "string",
200+
"description": "If result is 'failed', a short stable signature suitable for matching against docs/agent-reference/failure-patterns.md. Optional."
201+
}
202+
}
203+
},
204+
"sshFindings": {
205+
"type": "object",
206+
"description": "SSH-specific finding shapes. Fields below are the categories the playbook MUST cover; their internal shape is intentionally permissive in v0 and will be tightened once more SSH targets have been probed.",
207+
"additionalProperties": false,
208+
"properties": {
209+
"shellPrompt": {
210+
"type": "object",
211+
"additionalProperties": true,
212+
"description": "What the shell prompt looks like, banner contents, motd presence, etc."
213+
},
214+
"batchModeSupported": {
215+
"type": "object",
216+
"additionalProperties": true,
217+
"description": "Whether non-interactive ExecuteCommand-style probes succeeded vs needed a PTY."
218+
},
219+
"sudoBehavior": {
220+
"type": "object",
221+
"additionalProperties": true,
222+
"description": "Whether sudo prompts for a password, has NOPASSWD, or is not present."
223+
},
224+
"passwordChangeCommand": {
225+
"type": "object",
226+
"additionalProperties": true,
227+
"description": "Which password-change command path the target supports (passwd, chpasswd, vendor-specific CLI, etc.) — observed, not assumed."
228+
}
229+
}
230+
},
231+
"httpFindings": {
232+
"type": "object",
233+
"description": "HTTP-specific finding shapes. Fields below are the categories the playbook MUST cover; their internal shape is intentionally permissive in v0 and will be tightened once more HTTP targets have been probed.",
234+
"additionalProperties": false,
235+
"properties": {
236+
"authScheme": {
237+
"type": "object",
238+
"additionalProperties": true,
239+
"description": "Which authentication scheme(s) the target accepts (basic, bearer, api-key header, form-fill, cookie). Observed via WWW-Authenticate, login form inspection, etc."
240+
},
241+
"loginForm": {
242+
"type": "object",
243+
"additionalProperties": true,
244+
"description": "If form-fill is in play: form action URL, field names, hidden tokens (CSRF), redirect chain."
245+
},
246+
"cookieBehavior": {
247+
"type": "object",
248+
"additionalProperties": true,
249+
"description": "Session cookie names, flags, lifetimes; whether session cookies suffice for subsequent calls."
250+
},
251+
"apiDiscovery": {
252+
"type": "object",
253+
"additionalProperties": true,
254+
"description": "Discovered API endpoints relevant to the planned operations (e.g., user lookup, password change, key rotation). Sourced from vendor docs or probe responses; never invented."
255+
}
256+
}
257+
}
258+
}
259+
}

0 commit comments

Comments
 (0)