@ouro.bot/cli 0.1.0-alpha.745 → 0.1.0-alpha.747
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/changelog.json
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.747",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Create every nested host-backup directory as root-private before provenance verification.",
|
|
8
|
+
"Accept a missing OCI source label only on Sanctuary's exact historical alpha.742 image while retaining strict source provenance for every other image."
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"version": "0.1.0-alpha.746",
|
|
13
|
+
"changes": [
|
|
14
|
+
"Run packaged Sanctuary auditors with constrained root privileges so root-private inspection and staged policy inputs remain readable without widening file permissions.",
|
|
15
|
+
"Audit immutable container image identity from Docker's resolved top-level Image and validate the portable effective root Mounts contract, including private bind propagation, across real Docker inspect output."
|
|
16
|
+
]
|
|
17
|
+
},
|
|
4
18
|
{
|
|
5
19
|
"version": "0.1.0-alpha.745",
|
|
6
20
|
"changes": [
|
package/deploy/unraid/README.txt
CHANGED
|
@@ -42,6 +42,7 @@ Effective-spec audit helper:
|
|
|
42
42
|
docker image inspect "$AUDIT_EXPECTED_IMAGE" >"$INSPECT_DIR/image.json" || return $?
|
|
43
43
|
chmod 0600 "$INSPECT_DIR/container.json" "$INSPECT_DIR/image.json" || return $?
|
|
44
44
|
docker run --rm --pull=never --network=none \
|
|
45
|
+
--user 0:0 --read-only --cap-drop=ALL --security-opt=no-new-privileges \
|
|
45
46
|
--entrypoint /opt/ouro/deploy/unraid/audit-container-spec.sh \
|
|
46
47
|
--mount "type=bind,src=$INSPECT_DIR/container.json,dst=/audit/container.json,readonly" \
|
|
47
48
|
--mount "type=bind,src=$INSPECT_DIR/image.json,dst=/audit/image.json,readonly" \
|
|
@@ -310,7 +311,9 @@ Effective-spec audit helper:
|
|
|
310
311
|
const image = JSON.parse(fs.readFileSync(imagePath, "utf8"));
|
|
311
312
|
if (!Array.isArray(container) || container.length !== 1 || !container[0] || container[0].Image !== imageId) process.exit(1);
|
|
312
313
|
if (!Array.isArray(image) || image.length !== 1 || !image[0] || image[0].Id !== imageId) process.exit(1);
|
|
313
|
-
|
|
314
|
+
const source = image[0].Config?.Labels?.["org.opencontainers.image.source"];
|
|
315
|
+
const legacyAlpha742 = "sha256:681449ad47a2621705cd339b481e6339236b31dc65e195b1cf5025d0f2191d7d";
|
|
316
|
+
if (source !== "https://github.com/ourostack/ouroboros" && !(source === undefined && imageId === legacyAlpha742)) process.exit(1);
|
|
314
317
|
const expected = ["custom/usenet_health.sh", "custom/ouro-events/bootstrap-spool.sh", "custom/ouro-events/emit-event.mjs", "custom/ouro-events/emit-usenet-event.sh", "custom/ouro-events/install-usenet-guard.sh", "go.butler-lines", "crontab.butler-lines", "global-state"];
|
|
315
318
|
const expectedUid = 0;
|
|
316
319
|
const expectedGid = 0;
|
|
@@ -1444,6 +1447,7 @@ Update:
|
|
|
1444
1447
|
audit the staged template and runtime policy with the packaged auditor, then
|
|
1445
1448
|
remove the private stage before any Butler mutation:
|
|
1446
1449
|
docker run --rm --pull=never --network=none \
|
|
1450
|
+
--user 0:0 --read-only --cap-drop=ALL --security-opt=no-new-privileges \
|
|
1447
1451
|
--entrypoint /opt/ouro/deploy/unraid/audit-container-spec.sh \
|
|
1448
1452
|
--mount "type=bind,src=$STAGED_TEMPLATE,dst=/audit/sanctuary.xml,readonly" \
|
|
1449
1453
|
--mount "type=bind,src=$STAGED_RUNTIME_POLICY,dst=/audit/container-runtime.json,readonly" \
|
|
@@ -1784,7 +1788,7 @@ Backup:
|
|
|
1784
1788
|
if docker stop ouro-butler \
|
|
1785
1789
|
&& test "$(docker inspect --format '{{.State.Running}}' ouro-butler)" = false \
|
|
1786
1790
|
&& install -d -m 0700 -o 0 -g 0 "$BACKUP_TMP" "$BACKUP_TMP/runtime" "$BACKUP_TMP/agent" "$BACKUP_TMP/host" "$BACKUP_TMP/provenance" \
|
|
1787
|
-
&& install -d -m 0700 -o 0 -g 0 "$BACKUP_TMP/host/custom/ouro-events" \
|
|
1791
|
+
&& install -d -m 0700 -o 0 -g 0 "$BACKUP_TMP/host/custom" "$BACKUP_TMP/host/custom/ouro-events" \
|
|
1788
1792
|
&& install -m 0600 -o 0 -g 0 /dev/null "$BACKUP_TMP/host/inventory" \
|
|
1789
1793
|
&& backup_host_file /boot/config/custom/usenet_health.sh custom/usenet_health.sh \
|
|
1790
1794
|
&& backup_host_file /boot/config/custom/ouro-events/bootstrap-spool.sh custom/ouro-events/bootstrap-spool.sh \
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0"?>
|
|
2
2
|
<Container version="2">
|
|
3
3
|
<Name>Mendelow Cloud Butler</Name>
|
|
4
|
-
<Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.
|
|
4
|
+
<Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.747</Repository>
|
|
5
5
|
<Registry>https://github.com/ourostack/ouroboros/pkgs/container/ouroboros-butler</Registry>
|
|
6
6
|
<Network>host</Network>
|
|
7
7
|
<Shell>sh</Shell>
|
|
@@ -10,13 +10,12 @@ const EXPECTED_BINDS = [
|
|
|
10
10
|
"/mnt/user/appdata/sabnzbd/sabnzbd.ini:/run/sanctuary/sabnzbd.ini:ro",
|
|
11
11
|
];
|
|
12
12
|
const EXPECTED_MOUNTS = [
|
|
13
|
-
["/mnt/user/appdata/ouro-butler/runtime/.ouro-cli", "/home/ouro/.ouro-cli", true],
|
|
14
|
-
["/mnt/user/appdata/ouro-butler/agent/sanctuary.ouro", "/home/ouro/AgentBundles/sanctuary.ouro", true],
|
|
15
|
-
["/boot/config/custom/ouro-events/spool", "/run/ouro-events", false],
|
|
16
|
-
["/mnt/user/appdata/sabnzbd/sabnzbd.ini", "/run/sanctuary/sabnzbd.ini", false],
|
|
13
|
+
["/mnt/user/appdata/ouro-butler/runtime/.ouro-cli", "/home/ouro/.ouro-cli", true, "rprivate"],
|
|
14
|
+
["/mnt/user/appdata/ouro-butler/agent/sanctuary.ouro", "/home/ouro/AgentBundles/sanctuary.ouro", true, "rprivate"],
|
|
15
|
+
["/boot/config/custom/ouro-events/spool", "/run/ouro-events", false, "rprivate"],
|
|
16
|
+
["/mnt/user/appdata/sabnzbd/sabnzbd.ini", "/run/sanctuary/sabnzbd.ini", false, "rprivate"],
|
|
17
17
|
];
|
|
18
18
|
const LEGACY_ALPHA742_IMAGE = "sha256:681449ad47a2621705cd339b481e6339236b31dc65e195b1cf5025d0f2191d7d";
|
|
19
|
-
const LEGACY_ALPHA742_BINDS = EXPECTED_BINDS.slice(0, 2);
|
|
20
19
|
const LEGACY_ALPHA742_MOUNTS = EXPECTED_MOUNTS.slice(0, 2);
|
|
21
20
|
const EXPECTED_EXTRA_PARAMS = "--restart=unless-stopped --user=10001:10001";
|
|
22
21
|
function record(value) {
|
|
@@ -46,9 +45,8 @@ function auditSanctuaryContainerSpec(value, options) {
|
|
|
46
45
|
const mountContract = options.mountContract ?? "canonical";
|
|
47
46
|
if (mountContract === "legacy-alpha742" && options.expectedImage !== LEGACY_ALPHA742_IMAGE)
|
|
48
47
|
violations.push("legacy mount exception requires the pinned alpha.742 image ID");
|
|
49
|
-
const expectedBinds = mountContract === "legacy-alpha742" ? LEGACY_ALPHA742_BINDS : EXPECTED_BINDS;
|
|
50
48
|
const expectedMounts = mountContract === "legacy-alpha742" ? LEGACY_ALPHA742_MOUNTS : EXPECTED_MOUNTS;
|
|
51
|
-
if (
|
|
49
|
+
if (root.Image !== options.expectedImage)
|
|
52
50
|
violations.push("image does not match the reviewed exact local Docker image ID");
|
|
53
51
|
if (root.Path !== "node")
|
|
54
52
|
violations.push("effective container path must be node");
|
|
@@ -92,14 +90,11 @@ function auditSanctuaryContainerSpec(value, options) {
|
|
|
92
90
|
violations.push("container must not publish all exposed ports");
|
|
93
91
|
if (!isEmptyRecord(network?.Ports))
|
|
94
92
|
violations.push("effective network ports must be empty");
|
|
95
|
-
const binds = stringArray(host.Binds);
|
|
96
|
-
if (!binds || JSON.stringify([...binds].sort()) !== JSON.stringify([...expectedBinds].sort()))
|
|
97
|
-
violations.push("bind set does not match the selected Sanctuary mount contract");
|
|
98
93
|
const mounts = Array.isArray(root.Mounts) ? root.Mounts : [];
|
|
99
94
|
const normalizedMounts = mounts.map((mount) => {
|
|
100
95
|
const item = record(mount);
|
|
101
|
-
return item && item.Type === "bind" && typeof item.RW === "boolean" && typeof item.Source === "string" && typeof item.Destination === "string"
|
|
102
|
-
? [item.Source, item.Destination, item.RW]
|
|
96
|
+
return item && item.Type === "bind" && typeof item.RW === "boolean" && typeof item.Source === "string" && typeof item.Destination === "string" && item.Propagation === "rprivate"
|
|
97
|
+
? [item.Source, item.Destination, item.RW, item.Propagation]
|
|
103
98
|
: null;
|
|
104
99
|
});
|
|
105
100
|
if (normalizedMounts.some((mount) => mount === null)
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ouro.bot/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.747",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@ouro.bot/cli",
|
|
9
|
-
"version": "0.1.0-alpha.
|
|
9
|
+
"version": "0.1.0-alpha.747",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
12
12
|
"@azure/identity": "^4.13.0",
|