Files
FlociClone/docs/services/codeartifact.md
T
2026-09-22 08:57:00 -04:00

13 KiB

CodeArtifact

Protocol: REST JSON

Endpoint: http://localhost:4566

Floci supports the CodeArtifact control plane: domains, repositories, resource policies, tags, and public upstream (external) connections. Package publish/fetch through the CodeArtifact API itself is implemented for the generic format only, matching AWS's own restriction that PublishPackageVersion accepts only generic. The maven format is served through its own real package-manager-protocol proxy (mvn/Gradle publish and resolve both work against the URL GetRepositoryEndpoint returns); the remaining formats (npm, PyPI, NuGet, etc.) have no real proxy behind them yet.

Supported Actions

Action Description
CreateDomain Creates a domain (max 10 per account per Region), optionally with a KMS encryption key and initial tags.
DeleteDomain Deletes a domain; fails with ConflictException while it still contains repositories, and with ResourceNotFoundException for a missing domain (as AWS does, although the API reference does not list it).
DescribeDomain Returns a domain's full description, including its repository count.
ListDomains Lists domain summaries for the account and Region, paginated.
GetAuthorizationToken Issues a bearer token scoped to a domain, valid for 0 (12 hours) or 900-43200 seconds, required by the maven repository endpoint.
PutDomainPermissionsPolicy Attaches or replaces a domain's resource policy, versioned by policyRevision.
GetDomainPermissionsPolicy Returns a domain's current resource policy and revision.
DeleteDomainPermissionsPolicy Removes a domain's resource policy, optionally checked against policyRevision.
CreateRepository Creates a repository (max 1,000 per domain) with optional description, upstreams (max 10), and tags.
DeleteRepository Deletes a repository.
DescribeRepository Returns a repository's full description, including upstreams and external connections.
UpdateRepository Updates a repository's description and/or upstream list.
ListRepositories Lists repository summaries across all domains, optionally filtered by name prefix.
ListRepositoriesInDomain Lists repository summaries within one domain, optionally filtered by name prefix.
GetRepositoryEndpoint Returns the package-format-specific endpoint URL for a repository.
PutRepositoryPermissionsPolicy Attaches or replaces a repository's resource policy, versioned by policyRevision.
GetRepositoryPermissionsPolicy Returns a repository's current resource policy and revision.
DeleteRepositoryPermissionsPolicy Removes a repository's resource policy, optionally checked against policyRevision.
AssociateExternalConnection Attaches a fixed-catalog public upstream (e.g. public:npmjs) to a repository; mutually exclusive with repository upstreams.
DisassociateExternalConnection Removes a repository's external connection.
PublishPackageVersion Uploads a generic-format asset, creating or extending a package version; requires x-amz-content-sha256 and verifies it against the real hash of the bytes received.
DescribePackageVersion Returns a package version's status, revision, and origin.
GetPackageVersionAsset Downloads one asset from a package version by name, optionally pinned to a specific revision.
TagResource Adds or updates tags on a domain or repository ARN.
UntagResource Removes tags by key from a domain or repository ARN.
ListTagsForResource Lists the tags on a domain or repository ARN.

Domains and repositories are account and Region scoped and persisted through StorageFactory. DeleteDomain fails with ConflictException while the domain still contains repositories, matching AWS. PutDomainPermissionsPolicy/PutRepositoryPermissionsPolicy use the returned policyRevision for optimistic locking on subsequent updates, also matching AWS. Floci enforces AWS's own account and domain quotas: CreateDomain caps a single account at 10 domains per Region, and CreateRepository caps a single domain at 1,000 repositories, both returning ServiceQuotaExceededException with the offending resourceId/resourceType once reached.

AssociateExternalConnection accepts the same fixed set of AWS-hosted public upstreams documented for real CodeArtifact (public:npmjs, public:pypi, public:maven-central, etc.) and enforces the one-external-connection-per-repository limit AWS enforces. A repository can have upstream repositories or an external connection, but not both, matching AWS; CreateRepository and UpdateRepository also cap direct upstreams at 10, AWS's own repository limit.

PublishPackageVersion creates a package version in the Unfinished state when the unfinished flag is set, and Published otherwise; once Published, a repeat publish to the same domain/repository/package/version fails with ConflictException, matching AWS's real rule that a published version cannot accept additional assets. Every publish returns a fresh versionRevision, and each asset's hashes (MD5, SHA-1, SHA-256, SHA-512) are computed from the bytes Floci actually received, not echoed from the request. Floci enforces AWS's own published quotas for this action: a 5 GB max asset file size and a 350-asset cap per package version, both returning ServiceQuotaExceededException.

The Maven repository endpoint

GetRepositoryEndpoint for format=maven returns http://localhost:4566/codeartifact/maven/<domain>/<repository>/. Real Maven clients (mvn deploy, mvn dependency:get, Gradle) can publish to and resolve from that URL directly, the same way they would against real AWS CodeArtifact; it speaks the raw Maven repository layout (GET/PUT/HEAD over a group/artifact/version path), not the CodeArtifact JSON API. Every request needs a token from GetAuthorizationToken scoped to the domain being accessed, either as Authorization: Bearer <token> or as HTTP Basic with the token as the password (the username is ignored). Basic is what a real settings.xml, configured the way AWS documents for mvn (<server><username>aws</username><password>${env.CODEARTIFACT_AUTH_TOKEN}</password></server>), actually sends: Maven's HTTP wagon authenticates with Basic, not a custom header. A missing, invalid, expired, or wrong-domain token gets a 401 challenging Basic.

It is backed by a shared Reposilite container that Floci starts lazily on first use and reuses for every CodeArtifact repository; a CodeArtifact repository maps to its own Reposilite repository, provisioned automatically the first time it is published to or fetched from, and identified internally by a fresh id generated at CreateRepository time rather than a name derived from the domain/repository, so a repository deleted and recreated under the same name never inherits the previous one's artifacts. Two config knobs, FLOCI_SERVICES_CODEARTIFACT_MAVEN_IMAGE and FLOCI_SERVICES_CODEARTIFACT_MAVEN_URL, pin the image version or point at an already-running instance and skip container management, matching the pattern used elsewhere in Floci for sidecars.

AWS-compatible failures

Domain and repository names, tags, pagination, duplicate names, missing upstreams, policy-revision mismatches, and non-empty-domain deletes are validated. Every action also validates its required identifiers (domain, repository, package, packageVersion, asset) are present, returning ValidationException rather than a misleading ResourceNotFoundException for one that's simply missing from the request. Floci returns ValidationException, ConflictException, ResourceNotFoundException, and ServiceQuotaExceededException (tag limits) for deterministic conditions represented by local state. ConflictException, ResourceNotFoundException, and ServiceQuotaExceededException all carry the resourceId/ resourceType fields the wire model declares for them, matching the typed accessors the AWS SDK exposes on those exceptions.

AWS also models AccessDeniedException, InternalServerException, and ThrottlingException. Floci does not inject provider-side failures that cannot be derived from the request or emulator state.

Known limitations

  • Upstream cycles are not rejected. CreateRepository/UpdateRepository reject a repository naming itself as its own upstream and require each named upstream to already exist, but a longer cycle (repository A has B as an upstream, B has A) is not detected.
  • DeleteRepository does not check whether other repositories still reference it as an upstream. Deleting a repository leaves any repository that named it as an upstream pointing at one that no longer exists.
  • Cross-account domainOwner addressing has no authorization check. Passing a domainOwner that is not the caller's own account looks up that account's domain/repository with no trust-policy or permissions-policy enforcement, consistent with Floci's IAM enforcement being opt-in elsewhere, but worth knowing if you rely on domain-sharing semantics.
  • Package management beyond publish/describe/get-asset isn't implemented. ListPackages, ListPackageVersions, ListPackageVersionAssets, DeletePackageVersions, DisposePackageVersions, and UpdatePackageVersionsStatus don't exist yet; the only way to move a version from Unfinished to Published today is a follow-up PublishPackageVersion call that omits the unfinished flag.
  • The 5 GB asset size quota is nominal. PublishPackageVersion and the Maven repository endpoint both receive the request body as a single byte array before Floci ever checks its length, so a request already large enough to exhaust available heap fails before the quota check runs. The rejection (ServiceQuotaExceededException from PublishPackageVersion, HTTP 413 from the Maven endpoint) is correct for anything that does fit in memory; it is not itself a streaming size limit.
  • Deleting a CodeArtifact repository does not remove its Maven artifacts. The backing Reposilite repository and everything published to it are left behind (though never reused: see above); only the CodeArtifact-side metadata is deleted. This wastes storage inside the sidecar container over a long-running Floci process but is otherwise inert, since a deleted repository's endpoint already returns 404 through the proxy regardless of what Reposilite still holds.
  • Maven artifacts do not survive a Floci restart, even under persistent storage. The Reposilite sidecar container has no volume attached and is removed on shutdown along with everything published to it. CodeArtifact repository/domain metadata (including the stored mavenRepositoryId) survives a restart the same way any other Floci state does under persistent storage mode; the artifacts themselves do not, so the first Maven request after a restart re-provisions an empty Reposilite repository and returns 404 for anything published before the restart.
  • GetAuthorizationToken tokens are not revocable and are not tied to any IAM identity. Real CodeArtifact tokens are scoped to the calling principal's permissions; Floci's are scoped only to the domain named in the request; anyone who obtains one keeps the same domain-scoped access for its full lifetime.
  • The Maven repository endpoint does not resolve through upstream repositories or external connections. On real CodeArtifact, a repository with another repository configured as an upstream (UpdateRepository's upstreams) or with an AssociateExternalConnection to a public repository (public:maven-central, etc.) serves packages from those sources too, not just its own. Floci's Maven proxy only ever looks up the repository's own backing storage: a package that exists solely in an upstream, or only through an external connection, returns 404 through a repository that has it configured as one.

See the CodeArtifact API Reference.

Configuration

Variable Default Description
FLOCI_SERVICES_CODEARTIFACT_ENABLED true Enable or disable CodeArtifact
FLOCI_SERVICES_CODEARTIFACT_MAVEN_IMAGE dzikoysk/reposilite:3.6.3 Reposilite image used to serve the maven format
FLOCI_SERVICES_CODEARTIFACT_MAVEN_URL unset When set, use this URL and skip Reposilite container management
FLOCI_SERVICES_CODEARTIFACT_MAVEN_TOKEN unset name:secret access token for a pre-configured MAVEN_URL