@samirosamsam/aim 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aim",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Install deterministic Codex guardrails from natural-language block rules.",
5
5
  "author": {
6
6
  "name": "AIM"
package/README.md CHANGED
@@ -46,6 +46,19 @@ npx -y @samirosamsam/aim@latest rule add 'empêche de modifier package.json'
46
46
  npx -y @samirosamsam/aim@latest rule add 'empêche les calls GitHub qui ajoutent des collaborators'
47
47
  ```
48
48
 
49
+ For SaaS data targets described by a title or label, use Codex/provider tools first to resolve the concrete resource, then write the rule with `capture`:
50
+
51
+ ```bash
52
+ npx -y @samirosamsam/aim@latest capture \
53
+ --provider notion \
54
+ --tool fetch \
55
+ --args '{"url":"https://www.notion.so/..."}' \
56
+ --effect deny \
57
+ --agent codex \
58
+ --connection notion:codex \
59
+ --policy ~/.codex/aim/policy.json
60
+ ```
61
+
49
62
  Codex then calls the AIM hook before supported tool calls. A blocked Bash call returns the Codex `PreToolUse` deny shape:
50
63
 
51
64
  ```json
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samirosamsam/aim",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "AIM CLI for installing deterministic Codex tool-call guardrails.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -17,7 +17,14 @@ npx -y @samirosamsam/aim@latest setup --json
17
17
 
18
18
  If Codex reports that hooks need review, tell the user to run `/hooks`, inspect the AIM hook, and trust it. Do not claim active enforcement until the hook is trusted and a proof call blocks.
19
19
 
20
- 2. Add the user's requested block as a Codex guardrail rule:
20
+ 2. Choose the smallest enforceable path:
21
+
22
+ - For Bash commands and file edits, use `rule add`.
23
+ - For external data or SaaS access, first discover the concrete resource with that provider's tools, then use `capture`.
24
+ - If the user gives a human label such as a page title, folder name, channel name, repo label, database name, or "all subpages", do not reject it as "not a resource". Search/list/fetch with the provider plugin or MCP tools, pick the best exact match when confidence is high, and explain the choice. Ask only when several plausible matches remain or when a broad wildcard would be required.
25
+ - For hierarchical requests such as subpages, folders, databases, repos, or projects, enumerate the concrete children when the provider tools expose them and add rules for each resolved resource. If the provider cannot enumerate future children, block the resolved current resources and state that new children need another rule.
26
+
27
+ For local Codex rules:
21
28
 
22
29
  ```bash
23
30
  npx -y @samirosamsam/aim@latest rule add "<what the user wants to prevent>" --json
@@ -31,6 +38,21 @@ npx -y @samirosamsam/aim@latest rule add "empêche de modifier package.json" --j
31
38
  npx -y @samirosamsam/aim@latest rule add "empêche les calls GitHub qui ajoutent des collaborators" --json
32
39
  ```
33
40
 
41
+ For resolved MCP resources:
42
+
43
+ ```bash
44
+ npx -y @samirosamsam/aim@latest capture \
45
+ --provider "<provider>" \
46
+ --tool "<representative MCP tool>" \
47
+ --args '<representative MCP args JSON>' \
48
+ --resource "<stable provider resource id or path>" \
49
+ --effect deny \
50
+ --agent codex \
51
+ --connection "<provider>:codex" \
52
+ --policy ~/.codex/aim/policy.json \
53
+ --json
54
+ ```
55
+
34
56
  3. Prove the guardrail with a representative hook input before reporting success. Pick the proof that matches the rule:
35
57
 
36
58
  ```bash
@@ -58,7 +80,7 @@ npx -y @samirosamsam/aim@latest rule list --json
58
80
 
59
81
  ## Advanced Commands
60
82
 
61
- Use `capture`, `authorize`, `compile`, `add`, or `check` only for lower-level policy debugging. The normal public workflow is `setup`, `rule add`, proof, report.
83
+ Use `compile`, `add`, or `check` only for lower-level policy debugging. The normal public workflow is `setup`, then `rule add` for local Codex resources or provider discovery plus `capture` for MCP resources, then proof, then report.
62
84
 
63
85
  ```bash
64
86
  npx -y @samirosamsam/aim@latest capture \
@@ -75,7 +97,7 @@ If a command returns `questions`, ask for the missing command, file path, provid
75
97
 
76
98
  ## Scope
77
99
 
78
- - For Codex enforcement, prefer `rule add` over `compile`/`add`; it writes rules intended for the `PreToolUse` hook.
100
+ - For Codex enforcement, prefer `rule add` for Bash/files and `capture` for resolved MCP resources over `compile`/`add`; both write rules intended for the `PreToolUse` hook.
79
101
  - Prefer narrow resource patterns over `*`.
80
102
  - Codex hook guardrails are default-allow: no matching block means the tool call proceeds.
81
103
  - Treat `deny` as higher priority than `approval`, and `approval` as higher priority than `allow`.
package/src/engine.js CHANGED
@@ -214,7 +214,12 @@ export function compileCodexRulePrompt(prompt, context = {}) {
214
214
  }
215
215
 
216
216
  if (drafts.length === 0) {
217
- questions.push("Specify a Bash command, file path, or MCP provider/tool/resource to block.");
217
+ const providers = detectProviders(normalized).filter((provider) => provider !== "*");
218
+ if (providers.length > 0) {
219
+ questions.push(`Resolve the ${providers.join("/")} resource with that provider's search/list/fetch tools, then add an AIM capture rule with the stable resource id or path.`);
220
+ } else {
221
+ questions.push("Specify a Bash command, file path, or MCP provider/tool/resource to block.");
222
+ }
218
223
  }
219
224
 
220
225
  return { drafts: uniqueDrafts(drafts), questions };
@@ -531,7 +536,7 @@ function inferGithubCall(tool, args) {
531
536
  }
532
537
 
533
538
  function inferNotionCall(tool, args) {
534
- const page = cleanPart(args.page_id ?? args.pageId ?? args.id);
539
+ const page = cleanPart(args.page_id ?? args.pageId ?? args.id ?? notionPageId(args.url ?? args.page_url ?? args.pageUrl));
535
540
  const database = cleanPart(args.database_id ?? args.databaseId);
536
541
  if (page) return { access: inferAccess(tool), resource: `notion/pages/${page}` };
537
542
  if (database) return { access: inferAccess(tool), resource: `notion/databases/${database}` };
@@ -570,6 +575,14 @@ function githubRepo(args, suffix = "") {
570
575
  return owner && repo ? `repo/${owner}/${repo}${suffix}` : "*";
571
576
  }
572
577
 
578
+ function notionPageId(value) {
579
+ const text = String(value ?? "");
580
+ const dashed = text.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);
581
+ if (dashed) return dashed[0];
582
+ const compact = text.match(/[0-9a-f]{32}/i);
583
+ return compact?.[0] ?? "";
584
+ }
585
+
573
586
  function reasonFor(effect, access, resourcePattern) {
574
587
  if (effect === "deny") return `Block ${access} on ${resourcePattern}.`;
575
588
  if (effect === "approval") return `Require human approval for ${access} on ${resourcePattern}.`;