Skip to main content
← Back to list
01Issue
FeatureShippedSwamp ClubPublic
AssigneesNone

Relationships

#2200 Registry API: opt-in private visibility at publish time with fully backward-compatible defaults (prerequisite for CLI #2198)

Opened by swamp_lord · 9/16/2026· Shipped 9/16/2026

Goal and delivery order

Ship the Swamp Club service/API capability FIRST so a later Swamp CLI release can consume it. CLI follow-up: https://swamp-club.com/lab/2198.

An author must be able to explicitly publish an individual extension as private from its first publication, including into a PUBLIC collective. This must be an additive, opt-in API change: old clients and omitted-field requests must retain exactly their current behavior.

Existing implementation

Source reviewed at 4fea7909:

  • routes/api/v1/extensions/push.ts and lib/app/push-extension.ts do not accept or forward a visibility field.
  • routes/api/v1/extensions/confirm.ts and lib/app/confirm-push.ts do not accept or forward a visibility field.
  • lib/app/confirm-push.ts:216 derives first-publication isPrivate from namespaceOwnershipRepo.isNamespacePrivate(). The existing comment explicitly says the private-collective default bypasses the paid-plan gate.
  • Subsequent publications preserve the existing extension visibility.
  • Per-extension private/public state and post-publication visibility actions already exist in lib/app/set-extension-visibility.ts and routes/api/v1/extensions/[...path].ts. Explicit make-private actions have existing ownership/admin and entitlement checks.

Proposed additive API contract

Accept an optional visibility field on the publish request flow. At minimum, support the explicit value "private"; a shared "public" | "private" contract is reasonable if explicit public requests remain subject to existing visibility policy.

Example request metadata:

{
  "name": "@public-collective/internal-infrastructure",
  "version": "2026.09.16.1",
  "visibility": "private"
}

Thread the optional choice through POST /api/v1/extensions/push and POST /api/v1/extensions/confirm and their application request types. The resolved visibility must be applied when the extension is persisted, before public discovery or publish announcements. Do not implement this as publish-public followed by a separate make-private call.

Validate and authorize explicit requests using the existing ownership, private-extension entitlement, and collective-token rules. Resolve/check the choice consistently across initiation and confirmation; confirmation must not silently lose an explicit private choice. Reject unsupported or unauthorized explicit choices clearly, with no fallback to public.

Expose the applied visibility additively in the confirmation response so the future CLI can report the authoritative result. Preserve existing response fields, meanings, and success status codes.

Non-negotiable backward compatibility

When visibility is OMITTED:

  1. New extension + public collective: retain the current public default.
  2. New extension + private collective: retain the current private default, including the existing entitlement exception. Do not accidentally introduce a new paid-plan requirement on this legacy path.
  3. Existing extension: preserve its current visibility, whether public or private; do not recalculate it from collective visibility.
  4. Existing clients need no changes: keep the same endpoints, upload/confirmation flow, required fields, authentication paths, and release-channel behavior.
  5. No migration or bulk visibility changes to already published extensions or collectives.

Only a caller that supplies the new field opts into the new behavior. Public/private visibility and stable/rc/beta release channels remain independent.

Acceptance and regression tests

  • Deploy the service change independently before any CLI changes.
  • Test unmodified old-client payloads for every omitted-field case above, for both personal-key and collective-token publishing where currently supported.
  • Test explicit private publication under a public collective: extension metadata and archives are private from creation; unauthorized discovery/download and public announcements do not expose the extension.
  • Test republishing an existing private extension with omitted visibility and with explicit private: both remain private.
  • Test authorization/entitlement failures and invalid visibility values; no partial public publication or silent downgrade.
  • Test consistency between initiation and confirmation, including visibility supplied only at initiation, only at confirmation, or conflicting choices. Document a deterministic contract for those cases without changing the legacy omitted/omitted case.
  • Test additive response compatibility and unchanged stable/rc/beta behavior.
  • Document the supported wire field, values, omission semantics, errors, and rollout contract so CLI #2198 can leverage the service once deployed.

Scope

This issue is the service-side prerequisite. Manifest schema and CLI flags belong to #2198. Existing defaults must remain unchanged: the key new behavior is an explicitly private extension arriving privately in a public collective.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPEDTRIAGE+ 3 MOREFINDINGS+ 4 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

9/16/2026, 7:51:26 PM

Click a lifecycle step above to view its details.

03Sludge Pulse

Sign in to post a ripple.