{ "name": "verify-system-collections-refused", "comment": "A workflow gets nowhere near the collections SmartBotic runs on, even with defaultAccess read-write. This is the setting that matters: a blanket yes to every unlisted name. Reading projects exposes who may do what; writing it is a grant of access somebody gave themselves. Writing workflows edits another workflow's graph without passing a single permission check.\n\nThis was open. The runner and the webserver each kept their own list of protected collections and the two had drifted - the runner named five, the webserver ten, and \"projects\" was in neither. The list is one list now, in storage/system_collections.hpp, so a name added there is protected in both places at once.\n\nThe control is an ordinary collection written under the same defaultAccess, which must still succeed: this test is about protecting the system's own data, not about turning defaultAccess off.", "settings": { "storagePermissions": { "defaultAccess": "read-write" } }, "nodes": [ { "id": "n1", "name": "Trigger", "type": "click-trigger", "position": { "x": 0, "y": 0 }, "config": {} }, { "id": "projects", "name": "Read who may do what", "type": "storage-query", "position": { "x": 0, "y": 100 }, "config": { "collectionSource": "manual", "collectionManual": "projects" } }, { "id": "workflows", "name": "Read every workflow", "type": "storage-query", "position": { "x": 0, "y": 200 }, "config": { "collectionSource": "manual", "collectionManual": "workflows" } }, { "id": "users", "name": "Read the password hashes", "type": "storage-query", "position": { "x": 0, "y": 300 }, "config": { "collectionSource": "manual", "collectionManual": "users" } }, { "id": "escalate", "name": "Grant itself a project role", "type": "storage-insert", "position": { "x": 0, "y": 400 }, "config": { "collectionSource": "manual", "collectionManual": "projects", "documentData": "{\"name\": \"trespass\"}" } }, { "id": "control", "name": "An ordinary collection still works", "type": "storage-insert", "position": { "x": 0, "y": 500 }, "config": { "collectionSource": "manual", "collectionManual": "wfprobe_control_collection", "documentData": "{\"probe\": \"control\"}" } } ], "connections": [ { "sourceNodeId": "n1", "sourceOutput": "main", "targetNodeId": "projects", "targetInput": "data" }, { "sourceNodeId": "projects", "sourceOutput": "main", "targetNodeId": "workflows", "targetInput": "data" }, { "sourceNodeId": "workflows", "sourceOutput": "main", "targetNodeId": "users", "targetInput": "data" }, { "sourceNodeId": "users", "sourceOutput": "main", "targetNodeId": "escalate", "targetInput": "data" }, { "sourceNodeId": "escalate", "sourceOutput": "main", "targetNodeId": "control", "targetInput": "data" } ], "expect": { "projects": { "status": "completed", "output": { "error": "No read access to collection: projects" } }, "workflows": { "status": "completed", "output": { "error": "No read access to collection: workflows" } }, "users": { "status": "completed", "output": { "error": "No read access to collection: users" } }, "escalate": { "status": "completed", "output": { "success": false, "error": "No write access to collection: projects" } }, "control": { "status": "completed", "output": { "success": true } } } }