@actions-json/bridge 0.1.124 → 0.1.187
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/bin/cli.js +8 -0
- package/lib/register.js +139 -0
- package/lib/storage.js +37 -17
- package/package.json +2 -2
- package/seed/README.md +27 -0
- package/seed/scopes/README.md +10 -0
- package/seed/scopes/private/README.md +23 -0
- package/{template → seed}/storage.json +4 -3
- package/template/README.md +0 -74
- package/template/scopes/private/scope.json +0 -17
- package/template/scopes/private/sites/.gitkeep +0 -0
- package/template/scopes/public/scope.json +0 -17
- package/template/scopes/public/sites/.gitkeep +0 -0
- package/template/scopes/shared/.gitkeep +0 -0
package/bin/cli.js
CHANGED
|
@@ -10,6 +10,7 @@ const path = require('node:path');
|
|
|
10
10
|
const { spawn } = require('node:child_process');
|
|
11
11
|
const { ensureBinary } = require('../lib/install');
|
|
12
12
|
const { ensureStorageRoot } = require('../lib/storage');
|
|
13
|
+
const { install } = require('../lib/register');
|
|
13
14
|
|
|
14
15
|
// The primitive dictionary (browser-control tool catalog) ships with this
|
|
15
16
|
// package — it's a fixed runtime file, not user config. When the caller runs a
|
|
@@ -40,6 +41,13 @@ function withDefaults(args) {
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
async function main() {
|
|
44
|
+
// `install` is a wrapper-side subcommand (register the MCP server with the
|
|
45
|
+
// local coding agents); it does not touch the bridge binary or launch it.
|
|
46
|
+
if (process.argv[2] === 'install') {
|
|
47
|
+
process.exit(install());
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
43
51
|
let bin;
|
|
44
52
|
try {
|
|
45
53
|
bin = await ensureBinary();
|
package/lib/register.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// `npx @actions-json/bridge install` — register the actions-json MCP server with
|
|
4
|
+
// whatever coding agents are present, by calling each agent's own `mcp add`
|
|
5
|
+
// command. This removes the manual "copy the right claude/codex command" step
|
|
6
|
+
// from the install: we detect the agent, run its registrar, and report.
|
|
7
|
+
//
|
|
8
|
+
// Design: we shell out to each agent's OWN CLI (`claude mcp add …`,
|
|
9
|
+
// `codex mcp add …`) rather than hand-editing their config files, so the agent
|
|
10
|
+
// stays the source of truth for its own config format. Idempotent-ish: agents
|
|
11
|
+
// treat re-adding an existing server as an error, which we catch and report as
|
|
12
|
+
// "already registered" rather than failing the whole run.
|
|
13
|
+
|
|
14
|
+
const { execFileSync, execSync } = require('node:child_process');
|
|
15
|
+
|
|
16
|
+
// The canonical launch command every agent should register.
|
|
17
|
+
const SERVER_NAME = 'actions-json';
|
|
18
|
+
const LAUNCH = ['npx', '-y', '@actions-json/bridge', 'mcp'];
|
|
19
|
+
|
|
20
|
+
// Each supported agent: how to detect its CLI, and how to register a stdio MCP
|
|
21
|
+
// server with it. `addArgs` produces the argv for a spawn of `bin`.
|
|
22
|
+
const AGENTS = [
|
|
23
|
+
{
|
|
24
|
+
key: 'claude',
|
|
25
|
+
label: 'Claude Code',
|
|
26
|
+
bin: 'claude',
|
|
27
|
+
listArgs: () => ['mcp', 'list'],
|
|
28
|
+
addArgs: () => ['mcp', 'add', SERVER_NAME, '--', ...LAUNCH],
|
|
29
|
+
manual: `claude mcp add ${SERVER_NAME} -- ${LAUNCH.join(' ')}`,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
key: 'codex',
|
|
33
|
+
label: 'Codex',
|
|
34
|
+
bin: 'codex',
|
|
35
|
+
listArgs: () => ['mcp', 'list'],
|
|
36
|
+
addArgs: () => ['mcp', 'add', SERVER_NAME, '--', ...LAUNCH],
|
|
37
|
+
manual: `codex mcp add ${SERVER_NAME} -- ${LAUNCH.join(' ')}`,
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
// Is a CLI on PATH? Cross-platform: `command -v` on posix, `where` on win32.
|
|
42
|
+
function onPath(bin) {
|
|
43
|
+
try {
|
|
44
|
+
if (process.platform === 'win32') {
|
|
45
|
+
execSync(`where ${bin}`, { stdio: 'ignore' });
|
|
46
|
+
} else {
|
|
47
|
+
execSync(`command -v ${bin}`, { stdio: 'ignore', shell: '/bin/sh' });
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
} catch (_e) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Is the actions-json server ALREADY registered with this agent? We check first
|
|
56
|
+
// and never overwrite an existing config — a re-run must be a no-op, not a
|
|
57
|
+
// clobber (an install should only touch config when there's a reason to).
|
|
58
|
+
function alreadyRegistered(agent) {
|
|
59
|
+
if (!agent.listArgs) return false;
|
|
60
|
+
try {
|
|
61
|
+
const out = execFileSync(agent.bin, agent.listArgs(), { stdio: 'pipe' }).toString();
|
|
62
|
+
return out.includes(SERVER_NAME);
|
|
63
|
+
} catch (_e) {
|
|
64
|
+
// If listing fails we can't confirm; fall through to the add path, which
|
|
65
|
+
// still catches an "already exists" error rather than overwriting.
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Register with one agent. Returns { agent, status, detail }.
|
|
71
|
+
function registerOne(agent) {
|
|
72
|
+
if (!onPath(agent.bin)) {
|
|
73
|
+
return { agent: agent.label, status: 'absent' };
|
|
74
|
+
}
|
|
75
|
+
// Never replace an existing registration — skip if it's already there.
|
|
76
|
+
if (alreadyRegistered(agent)) {
|
|
77
|
+
return { agent: agent.label, status: 'already' };
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
execFileSync(agent.bin, agent.addArgs(), { stdio: 'pipe' });
|
|
81
|
+
return { agent: agent.label, status: 'registered' };
|
|
82
|
+
} catch (e) {
|
|
83
|
+
// Belt-and-suspenders: if the add still reports the name exists (race, or an
|
|
84
|
+
// agent we couldn't list), treat as already — do NOT clobber. Anything else
|
|
85
|
+
// is a real failure we surface with the manual command.
|
|
86
|
+
const out = `${e.stdout || ''}${e.stderr || ''}`.toLowerCase();
|
|
87
|
+
if (out.includes('already') || out.includes('exist')) {
|
|
88
|
+
return { agent: agent.label, status: 'already' };
|
|
89
|
+
}
|
|
90
|
+
return { agent: agent.label, status: 'failed', detail: agent.manual };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Detect + register across all known agents; print a human summary. Returns an
|
|
95
|
+
// exit code (0 if at least one agent got the server, 1 if none did).
|
|
96
|
+
function install() {
|
|
97
|
+
const results = AGENTS.map(registerOne);
|
|
98
|
+
const present = results.filter((r) => r.status !== 'absent');
|
|
99
|
+
|
|
100
|
+
process.stdout.write('\nactions.json — MCP registration\n');
|
|
101
|
+
for (const r of results) {
|
|
102
|
+
if (r.status === 'absent') continue;
|
|
103
|
+
const mark =
|
|
104
|
+
r.status === 'registered' ? '✓ registered' :
|
|
105
|
+
r.status === 'already' ? '✓ already registered' :
|
|
106
|
+
'✗ failed';
|
|
107
|
+
process.stdout.write(` ${mark}: ${r.agent}\n`);
|
|
108
|
+
if (r.status === 'failed') {
|
|
109
|
+
process.stdout.write(` run manually: ${r.detail}\n`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (present.length === 0) {
|
|
114
|
+
process.stdout.write(
|
|
115
|
+
' No supported coding agent (Claude Code or Codex) found on PATH.\n' +
|
|
116
|
+
' Install one, then re-run `npx @actions-json/bridge install`, or add it manually:\n'
|
|
117
|
+
);
|
|
118
|
+
for (const a of AGENTS) {
|
|
119
|
+
process.stdout.write(` ${a.manual}\n`);
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
const ok = present.some((r) => r.status === 'registered' || r.status === 'already');
|
|
123
|
+
if (ok) {
|
|
124
|
+
process.stdout.write(
|
|
125
|
+
'\nDone. Restart (or reconnect) your agent so it launches the server, then\n' +
|
|
126
|
+
'install the browser extension and connect it. See:\n' +
|
|
127
|
+
' https://yaniv256.github.io/actions.json/getting-started.html\n'
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
process.stdout.write('\n');
|
|
132
|
+
|
|
133
|
+
return present.length > 0 &&
|
|
134
|
+
present.some((r) => r.status === 'registered' || r.status === 'already')
|
|
135
|
+
? 0
|
|
136
|
+
: 1;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = { install, AGENTS, SERVER_NAME, onPath, registerOne };
|
package/lib/storage.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const fs = require('node:fs');
|
|
4
4
|
const os = require('node:os');
|
|
5
5
|
const path = require('node:path');
|
|
6
|
+
const { execFileSync } = require('node:child_process');
|
|
6
7
|
|
|
7
8
|
// Default storage location when the caller doesn't pass --storage-root.
|
|
8
9
|
// Lives in the user's home dir (not cwd) so it resolves no matter where the
|
|
@@ -14,39 +15,58 @@ function defaultStorageRoot() {
|
|
|
14
15
|
);
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
// The bundled seed skeleton (storage.json + scope READMEs + private placeholder),
|
|
19
|
+
// mirroring examples/actions.json.storage. The PUBLIC site maps are NOT bundled;
|
|
20
|
+
// they are cloned from the public maps repo on first run (see clonePublicMaps)
|
|
21
|
+
// so a fresh install arrives stocked with real, working maps to try.
|
|
22
|
+
const SEED_DIR = path.join(__dirname, '..', 'seed');
|
|
23
|
+
const PUBLIC_MAPS_REPO = 'https://github.com/yaniv256/actions.json.storage.public.git';
|
|
18
24
|
|
|
19
|
-
// Recursively copy the
|
|
20
|
-
|
|
21
|
-
function copyTemplate(src, dst) {
|
|
25
|
+
// Recursively copy the seed skeleton into the target.
|
|
26
|
+
function copySeed(src, dst) {
|
|
22
27
|
fs.mkdirSync(dst, { recursive: true });
|
|
23
28
|
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
24
|
-
if (entry.name === '.gitkeep') continue;
|
|
25
29
|
const s = path.join(src, entry.name);
|
|
26
30
|
const d = path.join(dst, entry.name);
|
|
27
31
|
if (entry.isDirectory()) {
|
|
28
|
-
|
|
32
|
+
copySeed(s, d);
|
|
29
33
|
} else {
|
|
30
34
|
fs.copyFileSync(s, d);
|
|
31
35
|
}
|
|
32
36
|
}
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
//
|
|
36
|
-
//
|
|
39
|
+
// Clone the public site maps into scopes/public so the workspace ships with
|
|
40
|
+
// something to try. Best-effort: if git is missing or the clone fails (offline,
|
|
41
|
+
// etc.), seed an empty scopes/public and tell the user how to get the maps —
|
|
42
|
+
// never fail the whole seed over the optional maps.
|
|
43
|
+
function clonePublicMaps(target) {
|
|
44
|
+
const publicDir = path.join(target, 'scopes', 'public');
|
|
45
|
+
if (fs.existsSync(publicDir) && fs.readdirSync(publicDir).length > 0) return;
|
|
46
|
+
try {
|
|
47
|
+
execFileSync('git', ['clone', '--depth', '1', PUBLIC_MAPS_REPO, publicDir], {
|
|
48
|
+
stdio: 'ignore',
|
|
49
|
+
});
|
|
50
|
+
process.stderr.write(`Cloned public site maps into ${publicDir}\n`);
|
|
51
|
+
} catch (_e) {
|
|
52
|
+
fs.mkdirSync(publicDir, { recursive: true });
|
|
53
|
+
process.stderr.write(
|
|
54
|
+
`Could not clone public site maps (need git + network). ` +
|
|
55
|
+
`Get them later with:\n git clone ${PUBLIC_MAPS_REPO} "${publicDir}"\n`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Ensure the storage root exists; create it from the bundled seed on first run,
|
|
61
|
+
// then clone the public maps. Returns the absolute path. Never overwrites
|
|
62
|
+
// existing storage.
|
|
37
63
|
function ensureStorageRoot(root) {
|
|
38
64
|
const target = root || defaultStorageRoot();
|
|
39
65
|
if (!fs.existsSync(target)) {
|
|
40
66
|
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
['scopes', 'private', 'sites'],
|
|
45
|
-
['scopes', 'public', 'sites'],
|
|
46
|
-
['scopes', 'shared'],
|
|
47
|
-
]) {
|
|
48
|
-
fs.mkdirSync(path.join(target, ...p), { recursive: true });
|
|
49
|
-
}
|
|
67
|
+
copySeed(SEED_DIR, target);
|
|
68
|
+
fs.mkdirSync(path.join(target, 'scopes', 'private'), { recursive: true });
|
|
69
|
+
clonePublicMaps(target);
|
|
50
70
|
process.stderr.write(`Created actions.json storage at ${target}\n`);
|
|
51
71
|
}
|
|
52
72
|
return path.resolve(target);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actions-json/bridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.187",
|
|
4
4
|
"bridgeBinaryVersion": "0.1.186",
|
|
5
5
|
"description": "Run the actions.json MCP bridge with npx — no Rust toolchain required. Downloads the prebuilt actions-json-mcp binary, bundles the primitive dictionary, and creates your storage workspace on first run.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"bin/",
|
|
18
18
|
"lib/",
|
|
19
19
|
"dictionary/",
|
|
20
|
-
"
|
|
20
|
+
"seed/",
|
|
21
21
|
"README.md"
|
|
22
22
|
],
|
|
23
23
|
"engines": {
|
package/seed/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# actions.json.storage
|
|
2
|
+
|
|
3
|
+
Your `actions.json.storage` workspace — the root/index that records storage configuration, mounted
|
|
4
|
+
scopes, and layout. It was created here on first run of `@actions-json/bridge`.
|
|
5
|
+
|
|
6
|
+
## Layout
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
storage.json Root manifest (mounts, visibility, sync policy)
|
|
10
|
+
scopes/
|
|
11
|
+
public/ Reviewed, reusable public site maps (cloned from the public maps repo)
|
|
12
|
+
private/ Your OWN owner-only storage — local by default (see its README)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## ⚠️ Privacy
|
|
16
|
+
|
|
17
|
+
`scopes/private` is where your browsing memory, observations, and unreviewed maps live. It is **local
|
|
18
|
+
and private by default** here in your home directory. If you later put this workspace under version
|
|
19
|
+
control, putting files in `scopes/private` does NOT make them private on its own — keep the repo
|
|
20
|
+
private, or mount `scopes/private` from your own **private** repo. See `scopes/private/README.md`.
|
|
21
|
+
|
|
22
|
+
## The public maps
|
|
23
|
+
|
|
24
|
+
`scopes/public` is cloned from
|
|
25
|
+
[actions.json.storage.public](https://github.com/yaniv256/actions.json.storage.public) so you have
|
|
26
|
+
working site maps to try immediately. Update them with `git -C scopes/public pull`, or repoint the
|
|
27
|
+
`public` mount in `storage.json` at your own public repo.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# scopes/
|
|
2
|
+
|
|
3
|
+
Each subfolder is a **mounted scope** — a separate storage area with its own visibility. Scopes are
|
|
4
|
+
usually git submodules pointing at their own repositories, so they can have different access than this
|
|
5
|
+
root repo.
|
|
6
|
+
|
|
7
|
+
- **public/** — reviewed, reusable public site-action maps (a git submodule to a public repo).
|
|
8
|
+
- **private/** — your OWN owner-only storage (see its README). Not included in this public example.
|
|
9
|
+
|
|
10
|
+
Add further scopes (e.g. `shared/<audience>/`) as separate repositories when you need them.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# scopes/private/ — placeholder
|
|
2
|
+
|
|
3
|
+
This is a **placeholder folder**, intentionally empty in the public example. Your private scope holds
|
|
4
|
+
owner-only browsing memory, observations, run logs, item indexes, and unreviewed action maps — content
|
|
5
|
+
that should never be public.
|
|
6
|
+
|
|
7
|
+
## ⚠️ Enforce privacy — two options
|
|
8
|
+
|
|
9
|
+
Putting files in this folder does NOT make them private on its own. Choose one:
|
|
10
|
+
|
|
11
|
+
1. **Keep the whole `actions.json.storage` repo private** (set the forked repo to Private). Then this
|
|
12
|
+
folder and its contents stay private along with everything else.
|
|
13
|
+
2. **Mount this folder from your OWN private repo** as a submodule, so private content lives in a
|
|
14
|
+
separate private repository even if the root repo is public:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
git submodule add https://github.com/YOUR-ORG/your-actions.json.storage.private.git scopes/private
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
and add a matching `private` mount to `storage.json`.
|
|
21
|
+
|
|
22
|
+
If you do neither and commit private files into a public repo, they will be exposed. The public example
|
|
23
|
+
links to no private repo, so nothing here is exposed by default.
|
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
"mount_type": "local",
|
|
14
14
|
"visibility": "private",
|
|
15
15
|
"default": true,
|
|
16
|
-
"description": "Your owner-only browsing memory, observations, overlays, run logs, item indexes, and unreviewed action maps. Local by default; point it at your
|
|
16
|
+
"description": "Your owner-only browsing memory, observations, overlays, run logs, item indexes, and unreviewed action maps. Local by default; point it at your OWN private repo to sync the same memory across your machines and agents (see scopes/private/README.md)."
|
|
17
17
|
},
|
|
18
18
|
"public": {
|
|
19
19
|
"path": "scopes/public",
|
|
20
|
-
"mount_type": "
|
|
20
|
+
"mount_type": "git_clone",
|
|
21
|
+
"repo": "https://github.com/yaniv256/actions.json.storage.public.git",
|
|
21
22
|
"visibility": "public",
|
|
22
|
-
"description": "Reviewed,
|
|
23
|
+
"description": "Reviewed, reusable public site-action maps (Trello, Gmail, Docs, GitHub, LinkedIn, Calendar, …). Cloned from the public maps repo on first run; pull to update, or point this at your own public repo."
|
|
23
24
|
}
|
|
24
25
|
},
|
|
25
26
|
"default_policy": {
|
package/template/README.md
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# actions.json storage
|
|
2
|
-
|
|
3
|
-
This **is** your `actions.json.storage` workspace — operational, not an example.
|
|
4
|
-
The bridge created it on first run (default: `~/.actions-json/storage`) and reads
|
|
5
|
-
and writes here as your agent browses. Your browsing memory, observations, and
|
|
6
|
-
action maps live in these folders.
|
|
7
|
-
|
|
8
|
-
## Scopes
|
|
9
|
-
|
|
10
|
-
Storage is organized by visibility. Each scope is a folder under `scopes/`; the
|
|
11
|
-
runtime discovers site maps under `scopes/<scope>/sites/<host>/`.
|
|
12
|
-
|
|
13
|
-
| Scope | What goes here | Git |
|
|
14
|
-
|---|---|---|
|
|
15
|
-
| `private/` | Your owner-only browsing memory, observations, run logs, and unreviewed maps. | Local by default. Opt in: back it with your own **private** repo to sync across your machines and agents. |
|
|
16
|
-
| `public/` | Reviewed, redacted maps **you publish** openly. | Opt in: point it at your own public repo. |
|
|
17
|
-
| `shared/<name>/` | Maps shared with a specific collaborator, **and** maps you pull **from** a source. | Opt in: one git remote per source. |
|
|
18
|
-
|
|
19
|
-
`private` and `public` are set up. Add `shared/<name>/` when you need it.
|
|
20
|
-
|
|
21
|
-
## Versioning a scope
|
|
22
|
-
|
|
23
|
-
Each scope is an ordinary folder, local until you choose to version it. Turn one
|
|
24
|
-
into a git repo when you want to sync or share it.
|
|
25
|
-
|
|
26
|
-
**Sync your private memory across machines** — back `scopes/private/` with your
|
|
27
|
-
own **private** repo so the same browsing memory follows your agent everywhere:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
cd ~/.actions-json/storage/scopes/private
|
|
31
|
-
git init && git add . && git commit -m "my private actions.json memory"
|
|
32
|
-
git remote add origin https://github.com/<you>/<your-private-storage>.git # private!
|
|
33
|
-
git push -u origin main
|
|
34
|
-
# on another machine: clone it into scopes/private instead of git init
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
This stays private — it is your repo, set to private. It only ever leaves your
|
|
38
|
-
machine if you point it at a remote, and `public`/`shared` promotion still
|
|
39
|
-
requires explicit review.
|
|
40
|
-
|
|
41
|
-
**Publish your public maps** — make `scopes/public/` your own public repo:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
cd ~/.actions-json/storage/scopes/public
|
|
45
|
-
git init && git add . && git commit -m "my public actions.json maps"
|
|
46
|
-
git remote add origin https://github.com/<you>/<your-public-storage>.git
|
|
47
|
-
git push -u origin main
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
**Pull the official map library** — vendor maps *from* a source into a shared
|
|
51
|
-
scope (the runtime discovers maps under `scopes/shared/<name>/`):
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
cd ~/.actions-json/storage/scopes/shared
|
|
55
|
-
git clone https://github.com/yaniv256/actions.json.storage.public.git actions-json
|
|
56
|
-
# maps now resolve from scopes/shared/actions-json/sites/<host>/
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Pulling from someone else's library uses the **shared** scope (inbound), not
|
|
60
|
-
`public` (which is for what *you* publish). Keep that boundary clear.
|
|
61
|
-
|
|
62
|
-
## Layout
|
|
63
|
-
|
|
64
|
-
```text
|
|
65
|
-
storage.json Root manifest — which scopes are mounted
|
|
66
|
-
scopes/
|
|
67
|
-
private/
|
|
68
|
-
scope.json Private scope manifest
|
|
69
|
-
sites/<host>/ Per-site maps, observations, overlays (local; sync via a private repo)
|
|
70
|
-
public/
|
|
71
|
-
scope.json Public scope manifest
|
|
72
|
-
sites/<host>/ Reviewed, redacted maps you publish
|
|
73
|
-
shared/<name>/ Add per-collaborator or per-source as needed
|
|
74
|
-
```
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"protocol": "actions.json.storage.scope",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"scope": "private",
|
|
5
|
-
"parent": "actions.json.storage",
|
|
6
|
-
"owner": {
|
|
7
|
-
"type": "person",
|
|
8
|
-
"id": "you"
|
|
9
|
-
},
|
|
10
|
-
"visibility": "private",
|
|
11
|
-
"default_policy": {
|
|
12
|
-
"observations": "store_freely",
|
|
13
|
-
"runs": "store_freely",
|
|
14
|
-
"overlays": "store_freely",
|
|
15
|
-
"action_maps": "draft_until_reviewed"
|
|
16
|
-
}
|
|
17
|
-
}
|
|
File without changes
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"protocol": "actions.json.storage.scope",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"scope": "public",
|
|
5
|
-
"parent": "actions.json.storage",
|
|
6
|
-
"owner": {
|
|
7
|
-
"type": "person",
|
|
8
|
-
"id": "you"
|
|
9
|
-
},
|
|
10
|
-
"visibility": "public",
|
|
11
|
-
"default_policy": {
|
|
12
|
-
"observations": "do_not_store_raw_private_observations",
|
|
13
|
-
"reports": "reviewed_public_artifact",
|
|
14
|
-
"action_maps": "reviewed_and_redacted",
|
|
15
|
-
"promotion": "review_required"
|
|
16
|
-
}
|
|
17
|
-
}
|
|
File without changes
|
|
File without changes
|