Skip to content

feat(validate): warn that storage registry and hook are not available yet - #889

Merged
ZacxDev merged 9 commits into
mainfrom
feat/validate-reserved-hook-registry
Nov 10, 2026
Merged

ZacxDev merged 9 commits into
mainfrom
feat/validate-reserved-hook-registry

Conversation

@ZacxDev

@ZacxDev ZacxDev commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

What

civitai app validate now reports the two reserved storage collection fields, registry and hook, as "not available yet". civitai.com refuses both at submit while registryExport and hooks are off in civitai main's APP_STORAGE_ENABLED_FEATURES.

They use the same path as the five existing gates (kind "log", write "anyone"/"owner", ttlSeconds, dailyWritesPerAuthor): a warning from storageFeatureGateWarnings, built by storageNotYet from the server's notYet text plus the CLI's "refuses this at submit today" suffix, and located at the field.

What an author sees:

storage.collections.<name>.registry is not available yet — collections published to registries arrive in a later phase of App Storage; remove it to keep the collection on Civitai only. civitai.com refuses this at submit today; …
storage.collections.<name>.hook is not available yet — permission hooks arrive in a later phase of App Storage; remove hook (the collection schema still applies). civitai.com refuses this at submit today; …

Order of checks (matches parseCollection)

  • registry: the server checks the feature switch before it checks the value or the shared-only rule, so any declared registry gets the gate.
  • hook: the server checks the switch only after parseHook accepts the shape. hookShapeAccepted copies the shape checks the schema states (allowed keys, file pattern and length, no node_modules, sha256 pattern, timeoutMs 1 to 500). A malformed hook gets the schema's error and no gate.
  • One known difference, documented in the code: the server's rule against a file inside outputDir is not copied. A hook there gets the gate warning here, where the server names outputDir.

There is no hook behaviour: no file is read and no digest is checked.

Tests

  • TestStorageFeaturesNotYetAvailableAreWarnings/{registry,hook}: each declared field gets exactly one gate warning with the exact text and field, and no error. A twin collection without the field gets nothing.
  • TestVendoredSchemaStillStatesTheFeatureGates: rows for both RESERVED schema sentences, so the gate list matches the schema.
  • TestStorageFeatureGateOrderMirrorsTheServer: six malformed-hook rows that get the schema error and never the gate.
  • Both fields are added to the finding-field ledger and the contract corpus.

Dependency

This needs #887, the re-vendored schema that adds registry and hook. Until #887 merges and this branch is rebased, the new rows fail on this branch because the vendored schema still rejects both fields as unknown properties.

🤖 Generated with Claude Code

ZacxDev and others added 2 commits November 10, 2026 12:53
… yet

civitai.com refuses two more storage collection fields at submit until
their features are switched on in APP_STORAGE_ENABLED_FEATURES
(registryExport, hooks): `registry` and `hook`. The canonical schema
admits both (re-vendored in #887), so a schema-clean manifest declaring
either validated clean and was then refused at submit.

Both are reported exactly like the other five feature gates: a WARNING
built by storageNotYet, carrying the server's notYet text verbatim plus
the CLI's "refuses this at submit today" suffix, located at the field.

Ordering mirrors parseCollection:
- registry: the switch is checked before the value and the shared-only
  rule, so any declared registry draws the gate.
- hook: the switch is checked only after parseHook accepts the shape, so
  hookShapeAccepted mirrors the shape checks the schema states, and a
  malformed hook gets the schema's error and no gate. Known divergence:
  the server's file-inside-outputDir rule is not mirrored (documented).

No hook behaviour: no hook file is read and no digest checked.

Tests: a ledger row per field (gate warning, exact text, field, no error,
and a twin without the field draws none), drift-guard rows for both
RESERVED schema sentences, six gate-ordering rows for malformed hooks,
and both fields in the finding-field ledger and contract corpus.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ring

A 201-character hook file (one over APP_STORAGE_HOOK_FILE_MAX_LENGTH, and
otherwise a valid path) gets the schema's maxLength error and no
"not available yet" warning. Mutation-checked locally: raising the length
bound in hookShapeAccepted turns exactly this row red.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ZacxDev
ZacxDev force-pushed the feat/validate-reserved-hook-registry branch from f2474da to 4c74e4a Compare November 10, 2026 18:53
ZacxDev and others added 4 commits November 10, 2026 12:56
…hook length rule (reverted next)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Restores 4c74e4a's tree exactly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rted next)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Restores 4c74e4a's tree exactly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ZacxDev
ZacxDev marked this pull request as ready for review November 10, 2026 19:04
ZacxDev and others added 3 commits November 10, 2026 13:11
…gates

Test rows only, no code change:
- a 200-character hook file is accepted and warned (the bound is inclusive)
- a .mjs hook file is warned (the pattern ends \.m?js$)
- timeoutMs 0 gets the schema error and no warning
- a hook without sha256 gets the schema error and no warning
- registry on a PRIVATE collection still gets the gate warning: the
  server checks !features.registryExport before the shared-only rule

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ry gates (reverted next)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Restores 8cbd3ab's tree exactly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ZacxDev

ZacxDev commented Nov 10, 2026

Copy link
Copy Markdown
Contributor Author

Audit at f44232bdc4.

  • Round 0 (requirements and deletion): proceed to the checklist.
    • D1 kept. hookShapeAccepted copies the schema's hook rules, the same way this file already copies the ttlSeconds bounds.
  • Round 1 (full checklist): no 🔴 and no 🟡, so the audit ladder ends here.
  • 🟢 1 and 🟢 2 are closed in c97edfff. The five surviving mutants each have a row now.
    • Each row went red under its mutant in CI run 42882896990.
    • The revert keeps tree 08ed5276.
  • 🟢 3 stays open. The server also refuses a hook file inside outputDir, and the CLI does not copy that rule. Closing condition: the PR that removes the hook warning once APP_STORAGE_ENABLED_FEATURES.hooks is true also ports that rule.
D1 — replace hookShapeAccepted's copy of the schema's hook rules with "hook declared and no schema error under storage.collections.<n>.hook" (reuse hasFindingUnder), removing a second copy of the schema's rules
1. test rows pin a 200-character file, a .mjs file, timeoutMs 0, a missing sha256, and the registry gate on a private collection

@ZacxDev
ZacxDev merged commit 5b0071d into main Nov 10, 2026
15 checks passed
ZacxDev added a commit to civitai/civitai-developer-docs that referenced this pull request Nov 10, 2026
…rts (#324)

civitai/cli#889 (released in v0.1.137) makes `civitai app validate` warn that
the RESERVED storage collection fields registry and hook are not available
yet, as it already does for the five other server-refused features. The
validate guide said the CLI rejects both as unknown properties, which is now
true only for v0.1.136 and earlier. Add both rows with the fix text the CLI
prints, note that a malformed hook gets the schema error instead, and keep
the older-CLI caveat.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant