Repository navigation
feat: core API — registry, capabilities, plans, Apply and retries - #2
Merged
Merged
Conversation
Phase 1 of the plan. The caller builds a Registry from Options and one Factory per provider (C9); NewRegistry refuses invalid options, incomplete descriptors, empty or non-slug IDs and duplicate IDs. Each Open hands the adapter a fresh client: egress guard outermost, then retries, then a per-request token that goes only to API hosts and never on a redirect, then the caller's round tripper (C1, C3, C4, C5). Every write is a Plan whose digest covers the provider, account, changes, what a destroy loses and the live state. Apply refuses an altered or expired plan and a plan whose live state moved (C6), and a destroy whose names were not typed back (C7), before anything is sent. A fake provider in the tests reaches its API only through the client it is given and exercises every path.
…surface Three policy tests read the package's syntax: every interface method, *Registry method and exported function field takes a context.Context first (C10); no package-level http.Client or Registry exists (C9); and no exported name the package has shipped disappears, so a removal has to be a deprecation instead. Each counts what it inspected and fails below a floor.
The getting-started guide covers building a registry, credentials, opening a provider, capabilities, plans, Apply and its refusals, and retries. The architecture guide explains the plan digest and the client's layering. CHANGELOG [Unreleased] lists the new API.
imanimanyara
marked this pull request as ready for review
November 3, 2026 13:29
Every job skips drafts, and the pull_request trigger had no ready_for_review type, so a PR opened as a draft and then marked ready reported its required checks as skipped, which the branch ruleset counts as passing. The policy test now fails when ci.yml skips drafts without listing ready_for_review; proven red by removing the type.
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.
Summary
Phase 1 ("Core") of cloudkit: the provider-independent API that every adapter and both consumers build on. Standard library only; every network call goes through the caller's
TransportviaNewHTTPClient.NewRegistry(Options, ...Factory),Open,Descriptors. Refuses a nil or default transport (C2), a missing credential source or logger (C5, C10), incomplete descriptors, empty or non-slug provider IDs, and duplicate IDs. No package-level state.Open. Egress guard outermost (C3, C4), then retries, then a per-request bearer token from theCredentialSource(C5), sent only to API hosts and never on a redirect, then the caller's round tripper.Capability,Access(Allowed,Denied,Unknown),CapSet; an unknown capability counts as a write.NewPlanwith a SHA-256 digest over provider, account, changes,Losesand live state; plan ID derived from the digest; 15-minutePlanTTL.Registry.Applywith theApplierinterface refuses an altered, expired or drifted plan (ErrConflict/PlanError) and a destroy without its names typed back (ErrConfirmationRequired), before any request.RetryPolicy(zero value: 3 tries, jittered backoff,Retry-Afterup to 30 s); never resends a non-idempotent request after an ambiguous failure;RateLimitErrorafter the budget.[Unreleased].All phase 0 exported symbols and behaviour are unchanged.
release.ymlis untouched; no tag.Test plan
make ci(fmt-check, vet, race tests, policy) green locallymake lint(golangci-lint v2.15.0): 0 issues