Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21c123ae84 | ||
|
|
13e4a23ee6 | ||
|
|
81b03c9404 | ||
|
|
f70f83635f | ||
|
|
5bcfef0ada | ||
|
|
eea8c5b784 |
No files matched your search
@@ -1,191 +0,0 @@
|
||||
# Row 283 (#1788) C2-01d design, draft 2 (Honker)
|
||||
|
||||
Brief: docs/plans/2026-10-20_case2-rows.md "C2-01d" at refactor 94c33a43c. Sources: the design at
|
||||
agents/gosalyn/work/case2/DESIGN.md b68d79663, the ruling after r11 (:207), the M12 paragraph (:300),
|
||||
1.1 (:755) and 1.2 (:817). Base 94c33a43c. Reviewer Webby, gate owner Sage. Nothing is built yet. The
|
||||
build waits for 282 to land (sage-2906).
|
||||
|
||||
## 1. Mapping (packages/library/src/mapping.mjs)
|
||||
|
||||
`supporting`:
|
||||
- Every universe kind takes an optional `supporting` list: plain `['name','books','playground','supporting']`,
|
||||
hybrid adds it to its seven keys, and a draft gets `['kind','name','playground','supporting']`.
|
||||
- Each value is checked as a playground prefix is: a string ending in `/` whose body passes `folder()`.
|
||||
- The output carries `supporting` on every universe, `[]` when absent, the way a draft carries
|
||||
`books: []`. classify then needs no `?? []`. The business writer writes the raw document
|
||||
(organization.mjs:195), not this output, so no business file changes shape.
|
||||
- The prefix rules, across every entry (ruling after r11):
|
||||
- A supporting prefix holding another supporting prefix, or one listed twice, refuses
|
||||
`library-mapping-invalid`.
|
||||
- A prefix equal to one of its own entry's book folders, or holding one, refuses `library-mapping-invalid`.
|
||||
- A prefix inside or holding another entry's book folder refuses `library-supporting-other-universe`.
|
||||
- Level comes from where the prefix sits, as for the playground: inside one of its own entry's books
|
||||
is book level, and outside every book is universe level. A draft's prefixes are all universe level.
|
||||
- Between the two lists (my choice, Q2):
|
||||
- A supporting prefix may equal a playground prefix of the same entry. That folder is writable.
|
||||
- A playground prefix may hold a supporting prefix of the same entry. The inner folder is supporting
|
||||
and the rest stays playground.
|
||||
- A supporting prefix that holds a playground prefix refuses `library-mapping-invalid`. classify
|
||||
checks supporting first, so that playground prefix could never match.
|
||||
- A supporting prefix equal to, holding or inside a playground prefix of another entry refuses
|
||||
`library-mapping-invalid`. Otherwise one path would have two universes.
|
||||
- The book loop at mapping.mjs:128-140 becomes a helper that both lists call with their own code and
|
||||
label. The playground's messages and codes stay byte-equal, so no existing test text moves.
|
||||
|
||||
`editor`:
|
||||
- The entry takes an optional `editor`. When present, it is an object with exactly the keys `name` and
|
||||
`email` (via `only()`). Each value is a string that is non-empty after trim and has no control
|
||||
character (`[\u0000-\u001f\u007f-\u009f]`), `<` or `>` (webby-0169 R1: git drops them from an ident
|
||||
and commits under a different name, so C2-02 would never see a failure). Anything else refuses
|
||||
`library-mapping-invalid`.
|
||||
- The output carries `editor: { name, email }` only when present, as `user` and `vaultPrefix` do. A save
|
||||
with no `editor` refusing is C2-02's job.
|
||||
|
||||
## 2. Scope (scope.mjs)
|
||||
|
||||
- `classify` gets a supporting loop before the playground loop (design 1.2). It returns `place(...)`
|
||||
with `{ scope: 'supporting', universe, book }`. The book is the book folder holding the prefix, or
|
||||
null at universe level and in a draft. The type and folder come from the first folder under the
|
||||
prefix, as for the playground.
|
||||
- The `.md` check stays first, so a `.canvas` or `.base` under a supporting prefix stays unmapped.
|
||||
- The comment above `classify` names the three prefix scopes and the order.
|
||||
|
||||
## 3. supportingPath (new supporting.mjs)
|
||||
|
||||
`supportingPath(mapping, universe, path, tree)` returns `path` or throws
|
||||
`LibraryError('library-write-story-path', ...)`. It is pure and reads no git.
|
||||
|
||||
- `tree` is the array `listTree` returns (reader.mjs:26, `{ mode, type, oid, size, path }`), so the
|
||||
C2-02 broker passes its listing as it is (Q3). A non-array `tree` throws a TypeError, because that is
|
||||
a caller bug, not a path class.
|
||||
- The checks run in this order, each with its own message naming the class:
|
||||
1. The path must be a string of at most 1,024 UTF-8 bytes (`Buffer.byteLength`).
|
||||
2. It must have no control character, using the same control class as `editor` (not `<` or `>`).
|
||||
3. It must have no backslash.
|
||||
4. It must not be absolute (a leading `/`).
|
||||
5. It must have no empty, `.` or `..` segment. That also catches `//` and a trailing `/`.
|
||||
6. `classify(mapping, path)` must give scope `supporting` and that same `universe`. This one check
|
||||
covers an unknown universe, an unmapped path, a `.canvas`, `.base` or attachment, a canon or
|
||||
story path, a playground path that isn't also supporting, and another universe's prefix. The scope
|
||||
rule then has one source, and M1 below hits both.
|
||||
7. Every proper prefix of the path (`a`, `a/b`, ...) and the path itself must not be in `tree` with
|
||||
mode `120000` (symlink) or `160000` (gitlink).
|
||||
8. No prefix of the path, and not the path itself, may equal a tree path or a tree directory
|
||||
(derived from the entries' paths) after `normalize('NFC').toLowerCase()` on both sides, unless
|
||||
it equals that tree path exactly. NFC as well as case, because APFS treats NFC and NFD forms of
|
||||
a name as one file (webby-0169 N1).
|
||||
Directories are checked too, because the folders under a supporting prefix are hers to name. A
|
||||
path in a tree that holds both `a.md` and `A.md` refuses, which matches R7.
|
||||
- The refusal messages quote the path with JSON, except for the control-character class, whose message
|
||||
leaves the path out.
|
||||
- The delete rule ("A delete also needs the path to exist at the tip as a 100644 blob", M12) isn't in
|
||||
the brief's supportingPath list. It stays with C2-02's delete (Q4).
|
||||
The C2-02 brief doesn't name it (only design :308), so BUILD.md carries it to C2-02 under Handoffs
|
||||
(webby-0169 Q4).
|
||||
- index.mjs exports `supportingPath`.
|
||||
|
||||
## 4. README (packages/library/README.md)
|
||||
|
||||
- Mapping: `supporting` and its rules, the cross-list rules, and `editor`.
|
||||
- Refusals: a `library-supporting-other-universe` row, and the new cases in the
|
||||
`library-mapping-invalid` row.
|
||||
- Scope: supporting first, then playground, then canon.
|
||||
- A new section, "Agent write paths", for supportingPath and its classes.
|
||||
|
||||
## 5. Callers of classify outside files owned (Q1 for Sage)
|
||||
|
||||
- survey.mjs:65 builds `{ canon: 0, playground: 0, unmapped: 0 }` and increments
|
||||
`scopes[classify(...).scope]`. A supporting file adds `supporting: NaN`, and formatSurvey (:92) never
|
||||
prints it. I propose a departure: add `supporting: 0` and print it, so the line becomes
|
||||
`scopes canon 5, playground 1, supporting 0, unmapped 3; indexed 6`. That re-pins survey.test:73 and
|
||||
adds a count test. Without it, the survey reports garbage once she marks a folder. The departure
|
||||
covers two files, packages/library/src/survey.mjs and packages/library/tests/survey.test.mjs.
|
||||
- No change in the rest, each for a reason:
|
||||
- reader.mjs:183 skips only unmapped, so supporting files are indexed like playground files.
|
||||
- R5 (:207) flags only canon to playground, as design 1.3 R5 says. A canon link to a supporting file
|
||||
raises nothing.
|
||||
- render.mjs:23 gives supporting a null badge. The supporting badge belongs to C2-10b (design :1415).
|
||||
- mirror.mjs:246 refuses only unmapped. Reading supporting files by scope is C2-05c's.
|
||||
- No bus or webui source filters on scope (git grep at 94c33a43c).
|
||||
- M9 already protects the whole `projects` key from agent edits (library-projects-protected.test). No
|
||||
test is added there.
|
||||
|
||||
## 6. Tests
|
||||
|
||||
- mapping.test:
|
||||
- T1: `supporting` at book level, at universe level, in a hybrid and in a draft. The output carries
|
||||
it, with `[]` when absent. The draft `deepEqual` at :48 gains `supporting: []`.
|
||||
- T2: one test per prefix rule.
|
||||
- These refuse `library-mapping-invalid`: no trailing `/`, a bad folder, one holding another, one
|
||||
listed twice, one equal to its own book, one holding its own book, one holding a playground
|
||||
prefix, and one overlapping another entry's playground.
|
||||
- These refuse `library-supporting-other-universe`: one inside another universe's book, and one
|
||||
holding another universe's book.
|
||||
- An equal same-entry playground passes.
|
||||
- T3: `editor` passes, and absent passes. It refuses `library-mapping-invalid` for a non-object, an
|
||||
array, an extra key, a missing key, an empty or blank value, a non-string, and a control character,
|
||||
`<` or `>` in either value.
|
||||
- scope.test, T4:
|
||||
- Supporting at book level, universe level and in a draft each give their universe and book.
|
||||
- A folder in both lists is `supporting`, and a playground-only folder is `playground`.
|
||||
- A supporting `.canvas` or `.base` is unmapped.
|
||||
- supporting.test (new):
|
||||
- T5 passes at book level, universe level, in a draft, in a both-lists folder, and at exactly 1,024 bytes.
|
||||
- T6 has one refusal per class against a fixture tree with a symlink, a gitlink and a case variant.
|
||||
The classes are:
|
||||
- unmapped, `.canvas`, `.base`, an attachment, canon, playground-only, another universe's
|
||||
supporting prefix, and an unknown universe;
|
||||
- absolute, `..`, `.`, `//`, a trailing `/`, a backslash, a C0 control and DEL;
|
||||
- a symlink folder, a gitlink folder, and a symlink at the path itself;
|
||||
- a case-variant file, a case-variant folder, and an NFD-form variant of an NFC tree name;
|
||||
- 1,025 bytes made with a multi-byte character, so bytes and characters differ.
|
||||
- Each asserts the code `library-write-story-path`.
|
||||
- business.test: T7 adds one assertion that `validateBusinessDocument` refuses
|
||||
`library-supporting-other-universe`.
|
||||
- survey.test (only if Q1 is approved): T8 counts one supporting file, and :73 is re-pinned.
|
||||
|
||||
## 7. Mutants (exact strings go in BUILD.md)
|
||||
|
||||
| Mutant | Change | Killed by |
|
||||
|---|---|---|
|
||||
| M1 | classify checks playground before supporting (the brief's mutant) | T4 both-lists, T5 both-lists |
|
||||
| M2 | the other-universe fail for supporting is dropped | T2 |
|
||||
| M3 | the symlink and gitlink check is dropped | T6 |
|
||||
| M4 | the case check is dropped | T6 |
|
||||
| M4b | check 8 drops `normalize('NFC')` | T6 NFD variant |
|
||||
| M5 | the byte length uses `path.length` | T6 1,025 bytes |
|
||||
| M6 | the `editor` control-character check is dropped | T3 |
|
||||
| M6b | the `editor` `<` and `>` check is dropped | T3 |
|
||||
| M7 | supportingPath skips the universe match | T6 other universe |
|
||||
| M8 | the supporting-holds-playground check is dropped | T2 |
|
||||
|
||||
## 8. Gate
|
||||
|
||||
- Webby approves the manifest.
|
||||
- The library and business suites and every scripts/test-*.sh are green on Sage's gate.
|
||||
- Timeouts (mos-1275): each package `timeout -k 10 1800`, each script `timeout -k 10 300`, each single
|
||||
file and mutant `timeout -k 10 600`. These come from my row 256 gate at 10:34Z.
|
||||
- Before in-review, grep packages/*/tests for 64-hex pins on the changed files and for the changed
|
||||
message text, then drift-check BASE..refactor.
|
||||
|
||||
## 9. Questions
|
||||
|
||||
- Q1 (Sage): approve the survey.mjs and survey.test.mjs departure in section 5?
|
||||
- Q2 (Webby): the cross-list rules in section 1?
|
||||
- Q3 (Webby): `tree` as the `listTree` array?
|
||||
- Q4 (Webby): the delete's 100644 check stays with C2-02?
|
||||
- Q5 (Webby): `editor` refuses only blank values and control characters, as the brief says. `<` and `>`
|
||||
would break a git ident. I'd leave them to C2-02's commit step unless you want them refused here.
|
||||
|
||||
## 10. Draft 2 (webby-0169)
|
||||
|
||||
- R1 folded: `editor` refuses `<` and `>` too, with T3 cases and mutant M6b.
|
||||
- Q2 accepted. BUILD.md records the tradeoff: refusing a supporting prefix that holds a playground
|
||||
prefix goes past the brief, but it is the fail-closed reading and uses an existing code. The cost
|
||||
is that she can't nest a playground under a supporting folder, though she can nest the other way.
|
||||
- Q3 accepted. Q4: carried to C2-02 under Handoffs in BUILD.md, and Sage was asked to add it to C2-02's brief.
|
||||
- N1 folded into check 8 (NFC and case), with an NFD case in T6 and mutant M4b.
|
||||
- N2: the survey.test:73 pin gains only `supporting`, and the count test is the only addition
|
||||
(mos-1330, its own commit).
|
||||
- N3: before the build, re-grep tests outside packages/library for a `deepEqual` of the mapping output
|
||||
on the build base.
|
||||
@@ -0,0 +1,192 @@
|
||||
# Row 287 design notes: C2-21, the grant executor for a library project (#1792)
|
||||
|
||||
Builder Megavolt, reviewer Dewey, gate owner Sage (sage-2910, Q226, mos-1310). Branch megavolt/row287, a
|
||||
doc-only draft off 94c33a43c, written during Gizmoduck's slot with local git only. The build starts on the
|
||||
candidates of row 285 (C2-08b, Scrooge) and row 226 (C2-13b, Gosalyn) and rebases onto their landings
|
||||
(Q177). Nothing here has been run.
|
||||
|
||||
The brief is "C2-21 the grant executor for a library project" in docs/plans/2026-10-20_case2-rows.md at
|
||||
94c33a43c. Its gate: Dewey approves the manifest; the bus suite, the Gitea Docker test and the install test
|
||||
are green on Sage's gate, along with every `scripts/test-*.sh`; a search of the test run's output for the
|
||||
fixture admin and seat tokens finds nothing.
|
||||
|
||||
## Sources (line cites at 94c33a43c)
|
||||
|
||||
- `packages/bus/src/gitea-grant.mjs`: the admin api (`adminApi`, no collaborator call yet), the seat api
|
||||
(`forkGet`, `fork`, `repos`), `identitySha256`, `REPO_PAGE`/`REPO_PAGES`.
|
||||
- `packages/bus/src/broker.mjs`: `#giteaRole` :2132, `#giteaTargets` :2149, `#giteaGrantBinding` and its
|
||||
block :2167-2196, `#giteaRecheck` :2200, `#giteaSteps` step 4 :2425-2441 and step 5 :2442-2473, the
|
||||
`grant.applied` body and notice :2480-2488, the host refusals `host-creative-role` :1106 and :1254.
|
||||
- `packages/business/src/business.mjs` :266-288: a `kind: "library"` project goes through `checkMapping`, and
|
||||
:286 refuses any role whose `publish` names a library project.
|
||||
- `packages/library/src/mapping.mjs`: a library entry carries `remote`, `branch` and an optional `user`.
|
||||
- `packages/bus/tests/gitea-grant.test.mjs` :297-334 pins the `grant.applied` body (`forks: [...]`) and the
|
||||
block; `fake-gitea-api.mjs` keeps collaborators as a list of logins with no permission.
|
||||
- `packages/bus/tests/gitea-grant-docker.test.mjs`: the scratch gitea/gitea:1.27.1 container; it uses
|
||||
`os.tmpdir()`.
|
||||
|
||||
## 1. Rulings, blockers and questions
|
||||
|
||||
- B1, the publish rule. `business.mjs:286` refuses any `publish` entry that names a library project
|
||||
("library repositories cannot be published by agents"). The brief's chief needs `publish: ["books"]`, and a
|
||||
creative seat needs the library project in `publish` for `#giteaRole` and `#giteaTargets` to pass. No test
|
||||
under packages/*/tests or scripts pins the :286 message (positive control: "publish names" hits
|
||||
agent-identity.test.mjs).
|
||||
- Ruling sage-2916 (18:42Z 10-22), files-owned extension: row 287 owns `packages/business/src/business.mjs`
|
||||
:283-291 and the `packages/business/tests/business.test.mjs` cases for it. Row 285 leaves business.mjs
|
||||
alone. Conditions:
|
||||
- The refusal is rewritten, not deleted. A library project in `publish` loads only for a creative
|
||||
instance (`CREATIVE_DEFINITIONS`) or the chief of staff, each with a gitea credential. Any other
|
||||
instance still refuses, with a new message that names the rule. Tests cover both sides. The grant path
|
||||
serves an allowed one with collaborator reach, never a fork. (To confirm on the base: how business.mjs
|
||||
names the chief, by definition `chief-of-staff` or by `launch.by`.)
|
||||
- Before in-review, grep 'packages/*/tests/*' and `scripts/test-*.sh` again for the old message text,
|
||||
with a positive control.
|
||||
- PRD 1.15 REQ-LIB-6 is the authority for this. If Mos changes 1.15 (sage-2914, `library.write`
|
||||
routing), check this text against what lands.
|
||||
- Q1 to Q4 below: Sage accepted them as stated assumptions (sage-2916). Dewey checks them in the round.
|
||||
- Q1, the hash. `identitySha256` covers identity, publish and remotes, not a project's kind or the role's
|
||||
definition name, and the level comes from the definition name. Proposal: add a `library` key
|
||||
(`{project: level}`) to the hash input only when a publish project is a library, so every non-library
|
||||
grant's hash stays byte-identical and no open grant turns `decision-mismatch` on upgrade.
|
||||
- Q2, the event. `grant.applied` and its notice carry `forks`, and the test at :322 pins that body.
|
||||
Proposal: `forks` stays (empty when every target is a library), and a `repositories:
|
||||
[{project, repository, level}]` key appears only when a library target exists. The notice names them the
|
||||
same way.
|
||||
- Q3, mixed raises. A creative raise must name only library projects (mos-1320 item 2). The chief may
|
||||
name a library project next to forked ones in one raise; step 4 forks the others and adds the collaborator
|
||||
on the library one. Proposal: allow that, and test it. Under sage-2916, any other non-creative instance
|
||||
can't hold a library project in `publish` at all, so the business file refuses it before any raise.
|
||||
- Q4, the token search for the Docker test. The fake API's tokens are fixtures and can be grepped. The
|
||||
Docker test's tokens are minted by the container at run time, so the gate grep can't know them in advance.
|
||||
Proposal: the Docker test captures its own diagnostics and asserts that no token it minted appears in
|
||||
them, and the gate greps the run's output for every fake-API fixture token.
|
||||
|
||||
### Early look, Dewey (dewey-0862, 18:53Z 10-22, on 5bcfef0ad, read only), folded
|
||||
|
||||
These replace the matching proposals in sections 2 and 3 where they differ.
|
||||
|
||||
- Q2 accepted. `forks` stays and is `[]` when every target is a library. `repositories:
|
||||
[{project, repository, level}]` appears only when a library target exists. `repository` is the remote
|
||||
URL, the same form as `forks`; the `full_name` that step 5 matched is asserted in a test and doesn't go
|
||||
in the body. The only src reader of `forks` is the notice (:2483). The notice drops its forks clause when
|
||||
the list is empty and adds "repositories: <url> (<level>)". A non-library notice keeps today's text.
|
||||
- The read line: "The token can read every path of this repository. It can't push to it, because the user
|
||||
is a read collaborator." The seat scope is still `write:repository` (:2189).
|
||||
- B-a: `\nForks:` (:2187) prints only when a fork target exists.
|
||||
- B-b: "Step 5 checks that this is only its forks." (:2193) is unchanged with no library target. With one, it
|
||||
reads "Step 5 checks that this is only its forks and the repositories above at their level."
|
||||
- B-c: `others` (:2181, :2194) splits. An untargeted library project in publish gets its own line, "It may
|
||||
also reach these repositories as a collaborator: <url> (<level>)", because a revoke leaves the
|
||||
collaborator entry and step 5 accepts it publish-wide. Forked others keep today's line. L8 covers B-a to
|
||||
B-c.
|
||||
- Q1 holds. Test: a project flipped to `kind: "library"` between the raise and the recheck gives
|
||||
`decision-mismatch` (L10).
|
||||
- Q3 holds. Library projects stay out of step 5's fork upstream set (:2446), so a fork of her repository
|
||||
refuses `gitea-reach-wider`; L4 covers it.
|
||||
- Q4 holds if the assertion covers what the test prints, TAP stdout and stderr, not only an in-test
|
||||
buffer. The Docker test prints one line, "minted N, hits 0", for the gate to grep.
|
||||
- Step 5 compares exactly the keys `admin`, `push` and `pull`. BUILD.md records F-B's actual `permissions`
|
||||
object, so an extra Gitea key can't pass or fail by accident.
|
||||
- The chief is named by definition `chief-of-staff`, not `launch.by`, matching broker `STAFF_TO` (:240) and
|
||||
row 286 (dewey-0860). A fired chief keeps its roles entry (instance-settings.mjs:355), so B-2 also loads a
|
||||
fired chief's entry.
|
||||
|
||||
### The definitions' gitea credential (dewey-0865)
|
||||
|
||||
At 94c33a43c, chief-of-staff.json and all six creative definitions have `credentials: []`, so `#giteaRole`
|
||||
(:2137-2143) would refuse them all `gitea-not-declared`. Row 287 doesn't add the credential. Row 285 (C2-08b)
|
||||
owns those role files, and its brief (case2-rows.md :1823-1824) gives each creative role and the chief
|
||||
`[{"service": "gitea"}]`, which Mos authorized in mos-1309 item 5. That is why 287 builds after 285 lands. Two
|
||||
notes for 285, not for this row:
|
||||
- The grant path reads only `service === 'gitea'`. The seat token's scopes come from `SEAT_SCOPES` in code,
|
||||
not from the definition. coder.json adds `scopes`, and 285's validator decides whether the bare form passes.
|
||||
- Five bus tests read roles/chief-of-staff.json directly (chief-of-staff, fire-revokes-grants,
|
||||
instances-verb, names, routes-verb), and 285's gate names the business suite, not the bus suite.
|
||||
- Settled (sage-2950, 19:06Z 10-22): 285's gate runs the bus suite whole (sage-2946), and Scrooge has the
|
||||
role.mjs no-scopes check. Dewey withdrew dewey-0865 (dewey-0867). Mos withdrew the mos-1332 item 3 publish
|
||||
fence (mos-1333), so business.mjs stays out of 285's files and sage-2916 stands as written.
|
||||
- Correction (sage-2958, Scrooge): role.mjs refuses `{"service": "gitea"}` with no scopes
|
||||
(checkGiteaScopes :100-111, util.mjs:42); only a host entry may omit them (:134). So 285's entries name
|
||||
their scopes, equal to SEAT_SCOPES (sage-2915). The chief-of-staff.json readers are seven, not five: add
|
||||
host-run and reload. 287's tests that build definitions give gitea entries `scopes: ["read:user",
|
||||
"write:repository"]`.
|
||||
|
||||
## 2. The change (proposed)
|
||||
|
||||
- Order in the executor: step 2 (user) and step 3 (mint) as today. Step 4, for each target: a library
|
||||
project gets `PUT /api/v1/repos/{owner}/{repo}/collaborators/{user}` with `{permission}` through the admin
|
||||
api, op `collaborator-add`, the `token` header, logged like every call. Expect 204, or anything else fails
|
||||
with `gitea-failed`. A non-library project forks as today.
|
||||
- The level: `write` when `CREATIVE_DEFINITIONS.includes(role.definition)`, `read` otherwise. The raise has
|
||||
no field for it; `giteaGrantCheck` still refuses any key other than method, agent, rotateBy and target.
|
||||
- Step 5: the upstream set stays for forks. A repository is accepted when it is the user's fork of a
|
||||
non-library publish upstream (today's rule), or when its `full_name` is a library publish project's
|
||||
`owner/repo` and its `permissions` are exactly `{admin: false, push: level === 'write', pull: true}`. Any
|
||||
other repository, a wider permission or `admin: true` refuses `gitea-reach-wider` with the repository
|
||||
named.
|
||||
- `#giteaRole`: the `CREATIVE_DEFINITIONS` refusal becomes "unless every project the raise names is a
|
||||
library project". `#giteaRole` gets the raise's project list from its two callers (the binding at
|
||||
:2168 and the recheck at :2201), so it can decide. The comment cites mos-1320 item 2 and keeps
|
||||
mos-1163 for every other project and every host grant. The host refusals at :1106 and :1254 and their
|
||||
tests stay as they are.
|
||||
- `#giteaTargets` returns `{project, upstream, library: true, repository, level}` for a library project and
|
||||
today's `{project, upstream, fork}` otherwise. `forkProblem` still runs for both: a library remote on
|
||||
another host refuses `remote-host-mismatch`, and one the seat user owns refuses `remote-not-fork`.
|
||||
- The block: a library target prints `Repository: <remote>, level <write|read>.` in place of its fork line,
|
||||
plus the brief's line "The token can write every path of this repository. Only the bus's path check
|
||||
limits it to supporting folders." for a `write` level. For a `read` level the line says the token can read
|
||||
every path. (The brief gives only the write line; Dewey can rule the read wording.)
|
||||
- Revoke deletes the token as today; the collaborator entry stays, as forks do. A fire sets
|
||||
`prohibit_login` as today. Neither path changes.
|
||||
- `scripts/case2-install.sh` (row 226's file): the chief of staff's instance gets `identity` and
|
||||
`publish: ["books"]`. If `#grantableAgent` refuses the chief as its own target, the row stops and goes to
|
||||
Sage. Read of :2037-2042 says it passes when the chief is `launch.by`; a test proves it.
|
||||
|
||||
## 3. Tests (proposed)
|
||||
|
||||
Docker (`gitea-grant-docker.test.mjs`), each fact first, before any code is trusted:
|
||||
- F-A: the admin token with `ADMIN_SCOPES` adds a collaborator to a repository the admin account doesn't
|
||||
own. F-B: `/user/repos` with the seat token lists that repository with the granted `permissions`. Either
|
||||
failing stops the row; the output goes to Mos.
|
||||
- F-C (recorded, not gating): a protected file pattern on her branch refuses a seat user's push to a story
|
||||
path while her own push passes. F-D (recorded): branch protection refuses a seat user's force-push while a
|
||||
normal push passes. Each logs its result as a diagnostic and doesn't fail the file; BUILD.md and a message
|
||||
to Mos carry them.
|
||||
|
||||
Fake API (`gitea-grant.test.mjs`, `fake-gitea-api.mjs`): collaborators carry a permission, `repoJson`
|
||||
returns `permissions`, and the PUT route requires a site admin token with `write:repository`.
|
||||
- L1 a creative definition gets `write`; L2 the chief gets `read`, including a mixed raise of the library
|
||||
project and a forked one (Q3).
|
||||
- L4 a repository with `push: true` for a read grant, or `admin: true`, or a fork of her library repository,
|
||||
refuses `gitea-reach-wider` naming it.
|
||||
- L5 revoke deletes the token and leaves the collaborator.
|
||||
- L6 a non-library project still forks, and its `grant.applied` body is byte-identical to today's.
|
||||
- L7 a creative raise naming a non-library project, or a library and a non-library one, refuses
|
||||
`gitea-not-declared`.
|
||||
- L8 the block holds the repository, the level and the brief's line, plus B-a to B-c (dewey-0862); the notice
|
||||
has no "forks: ." on a library-only grant.
|
||||
- L10 a project flipped to `kind: "library"` between the raise and the recheck gives `decision-mismatch`.
|
||||
- L9 the chief raises its own grant through `credential.mint`.
|
||||
- Install test: the business file gives the chief `identity` and `publish`.
|
||||
|
||||
Business (`business.test.mjs`, sage-2916): B-1 a creative instance with identity, a gitea credential and a
|
||||
library project in `publish` loads; B-2 so does the chief; B-3 any other instance with a library project in
|
||||
`publish` refuses with the new message; B-4 a creative instance or the chief without a gitea credential
|
||||
still refuses under the existing `publish needs identity and a gitea definition` rule. Mutant: M5 drop the
|
||||
creative-or-chief condition (any instance loads), killed by B-3.
|
||||
|
||||
Mutants: M1 drop the library-only condition from `#giteaRole` (the brief's), killed by L7. Others to list
|
||||
once the code exists: the level forced to `write` (L2), step 5's exact-permission check loosened to
|
||||
`push || pull` (L4), the fork path taken for a library project (L1, a fork call counted).
|
||||
|
||||
## 4. Gate plan (draft)
|
||||
|
||||
On Sage's CLEAR, with TMPDIR from `mktemp -d /mnt/storage/scratch/tmp/gXXXXXX`, stopping at the first red:
|
||||
the touched bus test files whole, then the mutants, the bus suite, the Docker test (checking for `^skip`
|
||||
first, since a missing image skips it), the install test, every `scripts/test-*.sh` under row 281's limits,
|
||||
then the token grep over the saved output. Timeouts and limits go in this file before the run.
|
||||
|
||||
## Runs
|
||||
|
||||
Filled in after the runs.
|
||||
Reference in new issue
Block a user