mirror of
https://github.com/civitai/civitai.git
synced 2026-09-20 22:08:18 +08:00
32239d2d4d
* feat(licensing): turn the SellMerge write paths on The contract half of yesterday's expand/contract. Every pod has known the label for eleven hours and prod carries zero rows using it, so the paths that were held back can open: the schema @default and the upload form's default set go back to five values, the "Sell merges using this model" option returns, and the refine that refused the member at the upsert contract is deleted. Measured before writing this, prod replica: 424,641 models hold Sell and lack SellMerge, and 0 hold SellMerge. Nothing wrote it while the paths were shut. The two decision cases are INVERTED rather than deleted, because what they guard was never really about SellMerge. Restrictions are emitted by ABSENCE, so a member missing from a default set produces no clause and therefore GRANTS the permission -- silently, with no badge a creator would notice and no type error. Both now derive the expected set from the enum (Object.values minus None) rather than from a hand-written list, so the next member added without wiring reddens. A list would have needed updating by whoever forgot. Both cases are renamed to what they now assert; a stale test name is a comment that survives every refactor. The decision docblock is deleted rather than reworded, since the decision expires with this PR. Controls: dropping SellMerge from the schema default, from the form default, or from the option list each redden, as does re-adding a withholding refine, as does the field ceasing to validate members at all -- that last one is what stops the accept-loop passing vacuously. An innocent comment reword stays green. The backfill does NOT ride this PR. It runs after this is deployed, because until then the refine rejects a save carrying the member and the edit form resubmits it untouched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(licensing): assert the three sites AGREE, not that every member is granted Five lanes on #4874; two findings were against my own work. The docblock stated the absence rule backwards -- it claimed a member missing from the granted array produces no clause and so GRANTS the permission. The emitter returns '' when the array INCLUDES the member, so absence emits the clause and RESTRICTS. The real hazard is one file over and about the clause map, not the default set. The parent's commit message repeated the inversion. The guard asserted a policy: both defaults equal to every enum member requires the next CommercialUse addition to be granted to every model by default, which forbids the expand/contract manoeuvre shipped eleven hours ago. Rewritten as the invariant -- the two defaults and the option list must AGREE -- so withholding a new member everywhere at once stays legal, while a member granted by default and missing from the options is caught. Three attempts, each caught by a control: a whole-file count broke because Rent is a substring of RentCivit and Sell of SellMerge; a per-member count misfired on the cascade's legitimate references. The render-site guard pins that the list is mapped whole. It does NOT cover the disabled predicate -- no text guard expresses that without naming members, which reintroduces the policy. Stated in the test as a gap. From the other lanes: the local-dev DDL was missing the enum value, so a fresh checkout would reject the first model create; the migration header and the backfill endpoint carried claims this PR made false. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore(seed): seed the five-value permission shape alongside the legacy ones No seeded row granted SellMerge, so the sell/merge split was unexercisable in local data. Tracked despite scripts/local-dev being gitignored -- the ignore rule does not apply to already-tracked files. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>