Repository navigation
feat(lease): owner namespaces, local owner sessions and private lease records - #66
Merged
Merged
Conversation
… records Owner decision of 2026-10-22 (memolabs-dev/memo-bridge#257): the owner's sessions reach every repository he owns, public and private. - issue_preflight: the owner namespaces memolabs-dev and guillaume-flambard; any other owner is still refused before any GitHub call. The receipt carries repository_private, GitHub's own answer. - private_owner_allowlist: the owner's local stdio server (mode stdio) is accepted next to the Mac runtime, with the same darwin, host, uid, 0600, fixed path and owner_sub checks; a second owner file, external-projects.json, enrolls the owner's checkouts outside MEMOLABS_ROOT; limit 100. - issue_lease: a lease on a private repository stores `subject` (the ref digest) instead of repo and issue, so the public ledger no longer publishes private repository names or Issue numbers. Clear records stay readable and lose their identity at their next heartbeat. Closes #65
Review of memo-bridge#257: a non-normalized path or more than 20 rows made memo-bridge drop the external projects file while the ledger still enrolled its repositories. Both sides now refuse the same files. Refs #65
…vate leases
Fix pass of memo-bridge#258.
Finding 3: sha256('<repo>#<n>') is enumerable (Issue numbers are small).
On 2026-10-22, hashing Issues 1 to 2000 of 7 repository names recovered 99
of the 122 lease refs, 27 on private repositories. For an enrolled private
repository the ref name and subject are now HMAC-SHA256 under the owner's
key (private_owner_allowlist.lease_key, a 0600 owner file on the Mac). The
record keeps a keyed body digest and no Issue update time. A private claim
without the key fails closed. Legacy records stay readable where they are;
a live legacy lease keeps working for its holder, and the next lease moves
to the keyed name.
Finding 2: allowed() grants a new private lease only when the call carries
MEMO_BRIDGE_LEDGER_OWNER_CALL=1, which Memo Bridge sets per call for the
owner's principals only. The holder's own verify and heartbeat do not need
it.
Refs memolabs-dev/memo-bridge#257
guillaume-flambard
added a commit
to memolabs-dev/memo-bridge
that referenced
this pull request
Oct 22, 2026
…cipals only Fix pass of #258, finding 2. hub:owner, hub:readonly and reader: on the Mac, and any principal where no private file was set, got the owner namespaces: tasks_list and task_next searched non-enrolled private repositories with the owner's gh token and returned titles and bodies. - withOwnerPrivateRepos attaches the namespaces only for the owner (isOwnerPrincipal: oidc:<owner_sub>, or the minted local OS user). - A repository matched only through the namespaces is searched with is:public; exact entries as before. Results are deduplicated. - task_claim goes through ledger.forOwner() for the owner only, which sets MEMO_BRIDGE_LEDGER_OWNER_CALL=1 for that call; the variable is never inherited from the server environment. memolabs-dev/.github#66 requires it before granting a new private lease. Refs #257
guillaume-flambard
added a commit
to memolabs-dev/memo-bridge
that referenced
this pull request
Oct 22, 2026
Fix pass of #258, finding 4. A stage run rewrote the live private-repos.json and remote.json the running runtime reads; with the old release that makes the Mac path fail closed until --install. configure now writes the policy files, a record of the live ones and, when the owner has none, a new lease-key.json under --out/owner-policy/. promote (called by --install right before the restart, under the enrollment lock) moves them into place, keeps a 0600 .bak of each live file, never replaces a live lease key, and refuses if a live policy changed since the stage run. The plist sets MEMO_BRIDGE_OWNER_LEASE_KEY_FILE for the keyed private lease names of memolabs-dev/.github#66 (finding 3). Refs #257
Contributor
Author
|
Fix pass after the security review of memo-bridge#258. Still DRAFT. Head
How finding 3 is fixed:
Tests: 14 new or changed tests were red first (2 failures, 12 errors), then the suite went green: 137 OK. Real CLI against GitHub: a claim without the marker is refused with "Repository privacy or enrollment mismatch", and nothing is written. Owner decision still open: deleting the historical clear and unsalted refs. That is destructive, and their commits may stay fetchable by SHA. Merge after memo-bridge#258. Deploy both together on the Mac (the lease key is already in place). |
guillaume-flambard
marked this pull request as ready for review
October 23, 2026 17:19
|
This pull request does not currently match the merge queue conditions, so it cannot be queued from here. The box comes back if it matches again. |
mergify Bot
added a commit
to memolabs-dev/memo-bridge
that referenced
this pull request
Oct 23, 2026
…nd remote) (#258) * feat(access): every owner project for the owner's principals (local and remote) Owner decision of 2026-10-22 (#257): the owner reaches every project he owns through Memo Bridge, public and private, in his namespaces memolabs-dev and guillaume-flambard, from his remote connector and from his local stdio session. - owner-private-repos: the minted local:<OS user> principal reads the Mac owner policy like oidc:<owner_sub>, on mac only; any other remote principal is still refused; other local principals get no private repository. Owner namespaces, limit 100. - coordinator pre-filter (allowedRepo): an exact entry first, then any repository of the owner's namespaces; the ledger decides public, enrolled private or refused. Any other owner never reaches the ledger. - external projects: a Mac-only 0600 owner file (owner-policy/external-projects.json) adds the owner's checkouts outside MEMOLABS_ROOT to the catalog, inside his home, outside private folders, origin checked. Kept out of the catalog snapshot export and the operator. - the stdio server gives its ledger child MEMO_BRIDGE_AGENT_MODE=stdio and MEMO_BRIDGE_HOST unless set; enrollment refusals map to repo_not_allowed. - remote.json and enrollment limits 100; Mac installer accepts the owner namespaces and enrolls external projects; bridge_info states the live write gate and the owner scope; docs/OWNER_SCOPE.md. Needs memolabs-dev/.github#65 for the stdio mode, the owner account namespace and private lease records on the ledger side. Closes #257 * fix(sandbox): a checkout directly in the home closes the checkout, not the home Found by the local end-to-end check of #257: for an owner external checkout such as ~/<name>, the folder holding the repository is the home itself. sandboxPaths denied it whole, which also closed every toolchain under the home (nvm, pnpm), so both the install and the recipe phase failed with "Operation not permitted". Close the checkout itself instead (its .env and the owner's working files); the worktree and the Git data stay reopened after it, and the private-folder list still covers the rest of the home. Refs #257 * fix(sandbox): keep the owner's mail export in the home root out of jobs Review of #257: in the recipe phase the home is open except the private denylist, which did not name ~/gmail.json; a job could print it to its log. Refs #257 * fix(sandbox): close the owner's home to recipes, not only the denylist Fix pass of #258, finding 1 (blocking). The recipe phase read every home file the denylist did not name: ~/.zshrc with its exported tokens, ~/.config secrets. A test script written through worktree_write_file could copy one into the worktree, and worktree_read_file would return it. The recipe profile now closes the home like the install phase: home denied, then the PATH tool roots and a few read-only toolchain caches, then the denylist on top, then the worktree, the job folder and the Git data. The denylist also names the shell startup files and the measured .config secrets. Seatbelt tests cover a fake home and the real one (byte counts only). Refs #257 * fix(access): owner namespaces and private claims for the owner's principals only Fix pass of #258, finding 2. hub:owner, hub:readonly and reader: on the Mac, and any principal where no private file was set, got the owner namespaces: tasks_list and task_next searched non-enrolled private repositories with the owner's gh token and returned titles and bodies. - withOwnerPrivateRepos attaches the namespaces only for the owner (isOwnerPrincipal: oidc:<owner_sub>, or the minted local OS user). - A repository matched only through the namespaces is searched with is:public; exact entries as before. Results are deduplicated. - task_claim goes through ledger.forOwner() for the owner only, which sets MEMO_BRIDGE_LEDGER_OWNER_CALL=1 for that call; the variable is never inherited from the server environment. memolabs-dev/.github#66 requires it before granting a new private lease. Refs #257 * fix(install): stage the owner policy, promote it only with --install Fix pass of #258, finding 4. A stage run rewrote the live private-repos.json and remote.json the running runtime reads; with the old release that makes the Mac path fail closed until --install. configure now writes the policy files, a record of the live ones and, when the owner has none, a new lease-key.json under --out/owner-policy/. promote (called by --install right before the restart, under the enrollment lock) moves them into place, keeps a 0600 .bak of each live file, never replaces a live lease key, and refuses if a live policy changed since the stage run. The plist sets MEMO_BRIDGE_OWNER_LEASE_KEY_FILE for the keyed private lease names of memolabs-dev/.github#66 (finding 3). Refs #257 --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related Issue and spec
Closes #65. Companion: memolabs-dev/memo-bridge#258 for memo-bridge#257 (merges first). Spec: owner decision of 2026-10-22; the scope is in memo-bridge
docs/OWNER_SCOPE.md.STAR receipt
Situation:
memolabs-dev/*only.repoandissuein clear, so private repositories' names and Issue numbers were published.Task: let the owner's sessions use every repository he owns without widening anyone else's access, and stop publishing private identities.
Actions:
issue_preflight:ORG_REPOcovers the owner namespacesmemolabs-devandguillaume-flambard; any other owner is still refused before any GitHub call.repository_private, GitHub's answer.PUBLIC_ALLOWLISTliteral is kept: deployed coordinators still parse it.private_owner_allowlist:stdio(the owner's local Memo Bridge) is accepted next toruntime, with the same darwin, host, uid, 0600, fixed path and owner_sub checks. Any other mode is refused.external-projects.json, enrolls the owner's checkouts outside MEMOLABS_ROOT; it is validated exactly as memo-bridge validates it.issue_lease:subject(the digest already used as the ref name) in place ofrepoandissue.Results:
subject.Verification
9ea7763(feature37d2366).python3 -m unittest discover -s tests -p 'test_*.py': 128 tests, OK.Repository privacy or enrollment mismatch;someone-else/xgivesRepository not in the owner namespaces allowlist.subject, with norepo,issueor name.owner/repo#ncan confirm a lease.Safety and delivery
Merge order: after memo-bridge#258. memo-bridge main at
8794838fails one coordinator test against this ledger (a personal-namespace case now reaches GitHub instead ofrepo_not_allowed).Rollback: revert. Leases written in the new form then read as "Lease identity mismatch" under the old code until released or reclaimed, so prefer rolling forward. Draft, not merged, not deployed.