Skip to content

Commit 751cecd

Browse files
Complete bundle for armoriq/armorCodex per CONTRIBUTING.md
Per @internet-dot's review comment requesting the full plugin bundle (not just the README entry). This commit adds the complete ArmorCodex plugin source tree, mirrored from armoriq/armorCodex@main: - README.md, LICENSE, SECURITY.md - .codexignore, .plugin-scanner.toml - hooks/hooks.json (8 hook events declared) - scripts/bootstrap.mjs, scripts/hook-router.mjs, scripts/policy-mcp.mjs - scripts/lib/ (13 lib modules: engine, intent, policy, audit-wal, etc.) - .agents/plugins/marketplace.json (per-plugin marketplace metadata, follows AgiFlow reference shape — name "armoriq", plugin name "armorcodex", category "Tools & Integrations", source URL pointing at the canonical github.com/armoriq/armorCodex repo) Excluded from the bundle: - node_modules/ (installed at runtime via package-lock.json) - tests/ (moved out of the plugin distribution dir per scanner compliance; lives at the repo root in the source repo now) Refs hashgraph-online#189
1 parent 268fd69 commit 751cecd

25 files changed

Lines changed: 4510 additions & 9 deletions
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "armoriq",
3+
"interface": {
4+
"displayName": "ArmorIQ"
5+
},
6+
"plugins": [
7+
{
8+
"name": "armorcodex",
9+
"source": {
10+
"source": "url",
11+
"url": "https://github.com/armoriq/armorCodex.git"
12+
},
13+
"policy": {
14+
"installation": "AVAILABLE",
15+
"authentication": "ON_INSTALL"
16+
},
17+
"category": "Tools & Integrations"
18+
}
19+
]
20+
}

plugins/armoriq/armorCodex/.codex-plugin/plugin.json

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,17 @@
2727
"longDescription": "ArmorIQ intent-based security enforcement for OpenAI Codex. Treat as a strong Bash guardrail and audit layer, not a complete boundary for every Codex capability. Codex hooks currently emit Bash, apply_patch, and MCP tool calls. ArmorCodex provides plan registration through MCP, intent-plan matching, permission gating, and post-run audit on those tools. Non-Bash activity (file edits, web search, app connectors) is gated where Codex emits hook events.",
2828
"developerName": "ArmorIQ",
2929
"category": "Security",
30-
"capabilities": [
31-
"MCP",
32-
"Hooks"
33-
],
30+
"capabilities": ["MCP", "Hooks"],
3431
"websiteURL": "https://armoriq.ai",
35-
"privacyPolicyURL": "https://armoriq.ai/privacy",
36-
"termsOfServiceURL": "https://armoriq.ai/terms",
32+
"privacyPolicyURL": "https://armoriq.ai/privacy-policy",
33+
"termsOfServiceURL": "https://armoriq.ai/terms-of-service",
3734
"brandColor": "#00E5CC",
3835
"composerIcon": "./assets/armoriq-logo.png",
3936
"logo": "./assets/armoriq-logo.png",
4037
"defaultPrompt": [
41-
"Register an intent plan, then run my Bash commands.",
42-
"Show the current ArmorCodex security policies.",
43-
"Block Bash commands that contain curl or wget."
38+
"Show me what security rules are protecting this project.",
39+
"Block any commands that fetch URLs or exfiltrate data.",
40+
"Walk me through your plan before running anything."
4441
]
4542
},
4643
"userConfig": {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Paths excluded from Codex plugin distribution + scanner analysis.
2+
# Test fixtures contain fake API keys (e.g., "ak_test_12345678") used only
3+
# for unit tests; these are not real secrets but confuse hardcoded-secret
4+
# detectors. node_modules is build artifact, never shipped.
5+
6+
node_modules/
7+
tests/
8+
*.test.mjs
9+
*.test.js
10+
*.spec.mjs
11+
*.spec.js
12+
.git/
13+
.DS_Store
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[ignore]
2+
rules = ["HARDCODED_SECRET"]
3+
paths = ["tests/", "tests/*.test.mjs"]

plugins/armoriq/armorCodex/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 ArmorIQ Inc.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# ArmorCodex
2+
3+
Intent-based security enforcement for OpenAI Codex. Hooks Codex's `Bash`, `apply_patch`, and MCP tool calls against a declared intent plan and policy rules. Blocks intent-drift, gates by natural-language policy rules, and ships signed audit logs to the ArmorIQ backend.
4+
5+
This directory is the plugin bundle. The full project lives at the repository root.
6+
7+
## Install
8+
9+
```bash
10+
curl -fsSL https://armoriq.ai/install_armorcodex.sh | bash
11+
```
12+
13+
Or via Codex marketplace:
14+
15+
```bash
16+
codex plugin marketplace add armoriq/armorCodex
17+
codex plugin install armorcodex@armoriq
18+
```
19+
20+
## What this bundle contains
21+
22+
- `.codex-plugin/plugin.json` plugin manifest (Codex spec)
23+
- `.codex/` Codex-specific config
24+
- `.mcp.json` MCP server registration (`armorcodex-policy`)
25+
- `hooks/` global hook scripts (`preToolUse`, `postToolUse`, `sessionStart`, `userPromptSubmitted`)
26+
- `scripts/` bootstrap, hook router, lib modules
27+
- `assets/` plugin icon
28+
29+
## What it does
30+
31+
| Surface | Behavior |
32+
|---|---|
33+
| `sessionStart` / `userPromptSubmitted` | Injects directive: Codex registers its intent plan via MCP before any tool runs |
34+
| `preToolUse` | Verifies tool against the registered plan and policy. Returns `{"permissionDecision":"deny",...}` for out-of-plan or policy-denied calls. |
35+
| `postToolUse` | Async audit row to ArmorIQ backend (fire-and-forget WAL) |
36+
| `permissionRequest` | Honors policy decisions before user is prompted |
37+
| MCP tools | `register_intent_plan`, `policy_update` (natural-language rules), `policy_read` |
38+
39+
## Documentation
40+
41+
- Full docs: https://docs.armoriq.ai/armorcodex
42+
- Source repo: https://github.com/armoriq/armorCodex
43+
- ArmorIQ platform: https://armoriq.ai
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Security Policy
2+
3+
## Reporting a Vulnerability
4+
5+
If you discover a security vulnerability in ArmorCodex, please report it privately:
6+
7+
- **Email**: security@armoriq.io
8+
- **Subject prefix**: `[ArmorCodex security]`
9+
10+
Please include:
11+
12+
- A description of the issue and the impact
13+
- Steps to reproduce
14+
- The plugin version affected (see `.codex-plugin/plugin.json`)
15+
- Any proof-of-concept or sample payloads
16+
17+
We aim to acknowledge reports within 2 business days and to ship a fix within 14 days for high-severity issues.
18+
19+
Do not file public GitHub issues for security vulnerabilities. Use the email above so we can coordinate a fix before public disclosure.
20+
21+
## Supported Versions
22+
23+
Only the latest minor release on the `main` branch receives security updates. Pin the immutable git tag (e.g., `v0.2.0`) in your plugin marketplace source for reproducibility.
24+
25+
## Scope
26+
27+
In scope:
28+
29+
- The plugin runtime under `plugins/armorcopilot/`
30+
- The MCP server `armorcodex-policy`
31+
- The hook scripts under `hooks/`
32+
- Audit pipeline + intent token issuance
33+
34+
Out of scope:
35+
36+
- The ArmorIQ backend (`api.armoriq.ai`) — report via the same email but use subject prefix `[ArmorIQ backend security]`
37+
- Third-party dependencies (file with the respective upstream maintainer)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# ArmorCodex Plugin Assets
2+
3+
This directory holds the visual assets the Codex plugin manifest
4+
(`.codex-plugin/plugin.json`) references. All files are PNG and live at the
5+
plugin root per the published spec.
6+
7+
## Current assets
8+
9+
| Path | Manifest field | Purpose |
10+
| --- | --- | --- |
11+
| `assets/armoriq-logo.png` | `interface.composerIcon` and `interface.logo` | Icon shown in the Codex composer UI and on plugin detail pages. |
12+
13+
## Optional follow-up
14+
15+
Drop additional screenshots here and add them to `interface.screenshots` in
16+
`.codex-plugin/plugin.json` when ready. Suggested set, in order:
17+
18+
- `screenshot-policy.png` (policy management view)
19+
- `screenshot-intent-drift.png` (intent drift block)
20+
- `screenshot-audit.png` (audit trail)
21+
22+
Notes:
23+
24+
- All paths must be relative and start with `./` per the spec.
25+
- Screenshot entries must be PNG and stored under `./assets/`.
26+
- ArmorIQ brand color: `#00E5CC` (teal).
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"hooks": {
3+
"SessionStart": [
4+
{
5+
"hooks": [
6+
{
7+
"type": "command",
8+
"command": "node ./scripts/bootstrap.mjs router",
9+
"statusMessage": "Starting ArmorCodex"
10+
}
11+
]
12+
}
13+
],
14+
"UserPromptSubmit": [
15+
{
16+
"hooks": [
17+
{
18+
"type": "command",
19+
"command": "node ./scripts/bootstrap.mjs router",
20+
"statusMessage": "Loading ArmorCodex intent policy"
21+
}
22+
]
23+
}
24+
],
25+
"PreToolUse": [
26+
{
27+
"matcher": "*",
28+
"hooks": [
29+
{
30+
"type": "command",
31+
"command": "node ./scripts/bootstrap.mjs router",
32+
"statusMessage": "Checking ArmorCodex policy"
33+
}
34+
]
35+
}
36+
],
37+
"PermissionRequest": [
38+
{
39+
"matcher": "*",
40+
"hooks": [
41+
{
42+
"type": "command",
43+
"command": "node ./scripts/bootstrap.mjs router",
44+
"statusMessage": "Checking ArmorCodex approval policy"
45+
}
46+
]
47+
}
48+
],
49+
"PostToolUse": [
50+
{
51+
"matcher": "*",
52+
"hooks": [
53+
{
54+
"type": "command",
55+
"command": "node ./scripts/bootstrap.mjs router",
56+
"statusMessage": "Auditing ArmorCodex command"
57+
}
58+
]
59+
}
60+
],
61+
"Stop": [
62+
{
63+
"hooks": [
64+
{
65+
"type": "command",
66+
"command": "node ./scripts/bootstrap.mjs router",
67+
"timeout": 30
68+
}
69+
]
70+
}
71+
]
72+
}
73+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Lazily install npm dependencies on first run, then dispatch to the
2+
// real hook-router or MCP server. This makes the plugin work after
3+
// `codex plugin install` or repo-local hook setup even when the plugin
4+
// directory has no node_modules.
5+
import { existsSync, writeFileSync, readFileSync } from "node:fs";
6+
import { spawnSync } from "node:child_process";
7+
import path from "node:path";
8+
import { fileURLToPath } from "node:url";
9+
10+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
11+
const pluginRoot = path.dirname(__dirname);
12+
const installedMarker = path.join(pluginRoot, "node_modules", ".armorcodex-installed");
13+
const packageFiles = [
14+
path.join(pluginRoot, "node_modules", "@armoriq", "sdk", "package.json"),
15+
path.join(pluginRoot, "node_modules", "zod", "package.json"),
16+
path.join(pluginRoot, "node_modules", "@modelcontextprotocol", "sdk", "package.json"),
17+
];
18+
19+
// The marker is only trusted when all expected packages are also present.
20+
// Partial installs (e.g. zod present, sdk missing) would previously pass
21+
// the per-file check and the dispatch would crash on a missing import.
22+
function installedOk() {
23+
if (!existsSync(installedMarker)) return false;
24+
if (!packageFiles.every(existsSync)) return false;
25+
try {
26+
const markerVersion = readFileSync(installedMarker, "utf8").trim();
27+
const pkg = JSON.parse(
28+
readFileSync(path.join(pluginRoot, "package.json"), "utf8")
29+
);
30+
return markerVersion === pkg.version;
31+
} catch {
32+
return false;
33+
}
34+
}
35+
36+
if (!installedOk()) {
37+
process.stderr.write("[armorcodex] installing dependencies (one-time)...\n");
38+
const result = spawnSync("npm", ["install", "--omit=dev", "--silent", "--no-audit", "--no-fund"], {
39+
cwd: pluginRoot,
40+
stdio: ["ignore", "ignore", "inherit"]
41+
});
42+
if (result.status !== 0) {
43+
process.stderr.write("[armorcodex] npm install failed (exit " + result.status + ")\n");
44+
process.exit(1);
45+
}
46+
try {
47+
const pkg = JSON.parse(
48+
readFileSync(path.join(pluginRoot, "package.json"), "utf8")
49+
);
50+
writeFileSync(installedMarker, pkg.version || "ok", "utf8");
51+
} catch {
52+
// best-effort — if we can't write the marker the next run will reinstall
53+
}
54+
}
55+
56+
// MCP servers and hook routers communicate with Codex via JSON-RPC / JSON
57+
// over stdio. Any non-JSON write to stdout corrupts the protocol and Codex
58+
// closes the transport. Redirect console.* to stderr so dependencies (the
59+
// ArmorIQ SDK in particular) can't accidentally pollute the channel.
60+
const _consoleRedirect = (...a) => {
61+
const line = a
62+
.map((x) => (typeof x === "string" ? x : JSON.stringify(x, null, 0)))
63+
.join(" ");
64+
process.stderr.write(line + "\n");
65+
};
66+
for (const m of ["log", "info", "warn", "error", "debug", "trace"]) {
67+
console[m] = _consoleRedirect;
68+
}
69+
70+
const target = process.argv[2];
71+
if (target === "router") {
72+
await import("./hook-router.mjs");
73+
} else if (target === "mcp") {
74+
await import("./policy-mcp.mjs");
75+
} else {
76+
process.stderr.write("[armorcodex] bootstrap: unknown target '" + target + "'\n");
77+
process.exit(2);
78+
}

0 commit comments

Comments
 (0)