diff --git a/README.md b/README.md index df6fe4c..532ed13 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Shared contracts and runtime libraries for CommerceKit GitHub Actions. This public repository is a pnpm monorepo, not a GitHub Marketplace Action. There is no root `action.yml`. -The current integration release is `0.0.2` for both packages, distributed under the `preview` dist-tag. APIs remain pre-1.0; verify registry publication before installation. Placeholder reserved versions, if published later, are not supported dependencies. +The source manifests prepare `0.0.3` for both packages under the `preview` dist-tag; the last verified publication is `0.0.2`. APIs remain pre-1.0; verify registry publication before installation. Placeholder reserved versions, if published later, are not supported dependencies. | Package | Responsibility | Consumers | | ------------------------------------------ | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | @@ -24,7 +24,7 @@ flowchart LR Provider rendering and delivery, Action inputs/outputs, summaries, lifecycle state machines and endpoint-specific validation remain in consumers. See [architecture](docs/architecture.md), the original [extraction audit](docs/extraction-audit.md), and the current [remaining extraction audit](docs/remaining-extraction-audit.md). -Installation requires GitHub Packages access, including for public packages. Configure the scope registry and credentials using [the authentication guide](docs/github-packages.md). Consumers must pin exact supported versions. The source manifests contain intended first preview versions; this is not evidence of publication. +Installation requires GitHub Packages access, including for public packages. Configure the scope registry and credentials using [the release configuration and authentication guide](docs/github-packages.md). Consumers must pin exact supported versions. The source manifests contain prepared preview versions; this is not evidence of publication. Develop with Node **24.21.0** and pnpm **12.6.0**: diff --git a/RELEASING.md b/RELEASING.md index 06a1648..01f005f 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,12 +1,12 @@ # Owner release procedure -Nothing is published by a feature PR or ordinary CI. Package versions are immutable. Never force, delete, overwrite or republish a version. All workflows run from main and use GITHUB_TOKEN; review the selected commit, changelog and external gates first. +Nothing is published by a feature PR or ordinary CI. Package versions are immutable. Never force, delete, overwrite or republish a version. All workflows run from main and use GITHUB_TOKEN; review the selected commit, changelog and external gates first. Complete the [release configuration checklist](docs/github-packages.md) for Actions permissions, package access and consumer authentication; no custom publishing secret is required. 1. Merge implementation PR after approval. 2. Verify main CI and CodeQL. 3. Optionally dispatch `reserve-package-names` with confirmation `RESERVE-COMMERCEKIT-PACKAGES`. It publishes only temporary unsupported `0.0.0-reserved.1` packages under `reserved`, never source implementations or `preview`/`latest`. Both versions are checked absent before publishing. If one succeeds and the second fails, stop for owner review rather than bypassing immutability checks. -4. Configure public visibility, repository association and Actions read access as documented in `docs/github-packages.md`. -5. Prepare a selected-package version/changelog PR. Source manifests currently express intended `0.0.2`, not publication evidence. +4. Configure public visibility, repository association and Actions read access using the [package access checklist](docs/github-packages.md#package-access). +5. Prepare a selected-package version/changelog PR. Source manifests currently prepare `0.0.3` for both packages; the last verified publication is `0.0.2`. Source versions are not publication evidence. 6. Merge the reviewed version PR. 7. Dispatch `publish-package`: package `notification-contract` or `ccv2-client`, channel `preview` or `stable`, exact confirmation `PUBLISH-COMMERCEKIT-PREVIEW` or `PUBLISH-COMMERCEKIT-STABLE`. Preview accepts nonzero `0.x.y` initial releases (including `0.0.1`) or `0.x.y-preview.n`; stable requires 1.0.0 or later without prerelease. The workflow checks version absence and successful CI/CodeQL for the exact main commit, runs full quality and the selected pack/install checks, and verifies clean generated files. It retains the tested tarball in runner temporary storage, verifies its SHA-256 immediately before publication, and publishes those exact bytes with `preview` or `latest` and lifecycle scripts disabled. No source-directory repack or artifact upload is involved. 8. Verify the exact package version in GitHub Packages and its visibility/access. @@ -35,10 +35,10 @@ Wait for publication success and verify the exact registry version before the se ```sh gh workflow run create-package-release.yml --ref main \ - -f package=notification-contract -f version=0.0.2 \ + -f package=notification-contract -f version=0.0.3 \ -f confirmation=CREATE-COMMERCEKIT-PACKAGE-RELEASE ``` -This creates `notification-contract-v0.0.2`; selecting ccv2-client creates its independent `ccv2-client-v` tag. Stable publication uses channel `stable`, a reviewed stable manifest version and confirmation `PUBLISH-COMMERCEKIT-STABLE`. +This creates `notification-contract-v0.0.3`; selecting ccv2-client creates its independent `ccv2-client-v` tag. Stable publication uses channel `stable`, a reviewed stable manifest version and confirmation `PUBLISH-COMMERCEKIT-STABLE`. Tags are an output of the verified release phase, not a publication trigger. This keeps failed publication from creating a misleading release tag and avoids relying on a token-created tag to trigger another workflow. Both release phases require explicit dispatch. The publish and Release jobs have `checks: read` to verify commit check results and `security-events: read` to verify exact-commit main CodeQL analyses and the absence of open alerts; CI remains read-only and publication has no contents-write permission. diff --git a/compatibility/tests/release-safety.test.mjs b/compatibility/tests/release-safety.test.mjs index 3d33940..bb66722 100644 --- a/compatibility/tests/release-safety.test.mjs +++ b/compatibility/tests/release-safety.test.mjs @@ -7,7 +7,7 @@ import { join } from 'node:path'; it('publication requires exact package/channel/confirmation and pre-1.0 version', () => { for (const name of ['notification-contract', 'ccv2-client']) expect(releasePlan(name, 'preview', 'PUBLISH-COMMERCEKIT-PREVIEW')).toMatchObject({ - version: '0.0.2', + version: '0.0.3', tag: 'preview', }); for (const args of [ diff --git a/docs/github-packages.md b/docs/github-packages.md index cc57ab8..a2279a0 100644 --- a/docs/github-packages.md +++ b/docs/github-packages.md @@ -1,48 +1,68 @@ # GitHub Packages authentication and owner setup -Packages target `https://npm.pkg.github.com`, associated with public source repository `commercekit-tools/action-kit`. A public source repository does not automatically prove the package visibility/access settings. No package is claimed published by this PR. +This is the configuration checklist for future package releases and consumer updates. The release sequence, dispatch confirmations and recovery steps live in [RELEASING.md](../RELEASING.md). -Repository and consumer `.npmrc`: +Packages use `https://npm.pkg.github.com` and are associated with public source repository `commercekit-tools/action-kit`. Source visibility does not prove package visibility, access or publication. The current source prepares `0.0.3`; verify registry availability before consumer installation. + +## Publishing repository + +Enable GitHub Actions and allow the pinned actions used by this repository, including CodeQL. Repository and organization policies must allow the permissions declared in the workflows: + +| Workflow | `contents` | `packages` | `checks` | `security-events` | +| ---------------------------- | ---------- | ---------- | -------- | ----------------- | +| `publish-package.yml` | read | write | read | read | +| `create-package-release.yml` | write | read | read | read | +| `reserve-package-names.yml` | read | write | — | — | + +**No custom Actions secret is required for package publication or GitHub Release creation.** GitHub supplies `secrets.GITHUB_TOKEN` automatically for each workflow run. The workflows pass it as `NODE_AUTH_TOKEN` for GitHub Packages and `GH_TOKEN` for GitHub API operations where needed. Do not create or commit a replacement token, SAP credentials or notification webhook secrets for package release jobs. Consumer Sandbox/provider tests have their own configuration in the consumer repositories. + +Both release workflows require dispatch from `main`. Before publication, the exact main commit must have successful `quality`, all three `cross-platform` checks and `analyze`, plus a complete main CodeQL analysis without errors, warnings or open alerts. A green feature-branch run cannot satisfy the main analysis requirement. Fix missing permissions or check evidence instead of bypassing the release gates. Action Kit is public; if its visibility changes, re-evaluate CodeQL availability before configuring releases. + +No protected publication environment is currently attached to the jobs. If owners choose to add one, configure its protections first, then review a workflow change attaching that environment; creating an environment alone does not protect these workflows. Manual confirmations remain required. + +## Package access + +For each package, open its GitHub Packages settings and verify the following after first publication and before subsequent consumer updates: + +- Visibility is **Public** and the associated source repository is `commercekit-tools/action-kit`. +- The publishing repository has package write access, through inherited repository access or explicit **Manage Actions access**. +- Consumer repositories have **Read** permission under **Manage Actions access** as listed below. + +| Package | Consumer repositories | +| ----------------------- | ------------------------------------------------------------------------------------------- | +| `notification-contract` | `commercekit-tools/notify`, `commercekit-tools/ccv2-build`, `commercekit-tools/ccv2-deploy` | +| `ccv2-client` | `commercekit-tools/ccv2-build`, `commercekit-tools/ccv2-deploy` | + +Grant the future Check repository contract access only when that repository exists and needs installation. Verify exact-version installation using each consumer repository's own workflow token; successful installation with an owner's local token does not verify Actions access. + +## Consumer CI + +Keep the scope registry in the source-controlled `.npmrc`, without credentials: ```ini @commercekit-tools:registry=https://npm.pkg.github.com ``` -Local contributors need a classic PAT with `read:packages` (and organization SSO authorization when required). Put authentication in **user-level** npm configuration or an ephemeral environment-managed file, never repository files. Never commit package tokens. `pnpm install` in this source workspace fetches public dependencies from npm; scope auth is only needed for installed published CommerceKit packages. - -The publishing repository uses `GITHUB_TOKEN` with `packages: write`. Consumer Action repositories need package **Manage Actions access** read permission. After the owner grants access, consumer workflows can use their own `GITHUB_TOKEN`: +Consumer workflows use their own automatic `GITHUB_TOKEN` after the package access grants above. Preserve the consumer's pinned checkout/setup-node actions and configure setup-node with `registry-url: https://npm.pkg.github.com` and `scope: '@commercekit-tools'`. The relevant job permissions and install step are: ```yaml permissions: contents: read packages: read steps: - # Include pinned checkout/setup-node steps in the consumer workflow. - # Configure setup-node registry-url: https://npm.pkg.github.com + # Existing pinned checkout/setup-node steps configure the registry above. + - run: corepack enable - run: pnpm install --frozen-lockfile env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} ``` -Pin exact versions only after they are published and accessible: - -```json -{ - "dependencies": { - "@commercekit-tools/notification-contract": "0.0.2", - "@commercekit-tools/ccv2-client": "0.0.2" - } -} -``` +Pin exact versions only after they are published and accessible. For the prepared release, Notify needs `@commercekit-tools/notification-contract` at `0.0.3`; Build and Deploy need both packages at `0.0.3`. Regenerate and commit each consumer's lockfile and standalone Action bundle using its documented commands, then run its complete quality gate before pushing. Avoid dependency ranges, local links, git dependencies or copied library source in released Actions. -Install only the packages that a consumer needs; Notify and future Check do not need ccv2-client. Avoid runtime dependency ranges for bundled Actions. +Users running an already bundled Action do not need package registry credentials. Package authentication is needed when installing dependencies to develop or rebuild it. -Post-publication owner checklist (not performed by this task): +## Local contributors -- Set each package visibility to **Public**. -- Confirm source repository association: `commercekit-tools/action-kit`. -- For notification-contract grant read Actions access to `commercekit-tools/notify`, `commercekit-tools/ccv2-build`, `commercekit-tools/ccv2-deploy`, and future `commercekit-tools/check` once it exists. -- For ccv2-client grant read Actions access to `commercekit-tools/ccv2-build` and `commercekit-tools/ccv2-deploy`. -- Verify exact-version installation using each consumer repository token. +GitHub Packages installation requires authentication, including for public packages. Use a classic personal access token with `read:packages`, authorized for organization SSO when required. Store authentication in **user-level** npm configuration or an ephemeral environment-managed file; never in a repository. Configure registry authentication there to reference `NODE_AUTH_TOKEN` rather than storing the token value. Use `npm config get userconfig` to confirm the selected file, especially when an IDE overrides it; do not print authentication settings. -The repository currently has no configured protected publication environment. Add `environment: package-publish` to the publication job after owners configure and verify its protections; manual main-only confirmations remain mandatory regardless. +Supply `NODE_AUTH_TOKEN` through the local credential manager or secret environment, and do not print it. This token is for package installation; normal releases use the workflows above. Running `pnpm install` in the Action Kit source workspace fetches public dependencies from npm and does not require package credentials. An authenticated `gh` session with repository workflow access is needed only when dispatching or inspecting workflows from the command line. diff --git a/docs/remaining-extraction-audit.md b/docs/remaining-extraction-audit.md index c5fba55..40639ba 100644 --- a/docs/remaining-extraction-audit.md +++ b/docs/remaining-extraction-audit.md @@ -28,7 +28,7 @@ Compared current remote main and clean local consumer branches on 2026-11-11. Th ## First implementation -The new exports are additive and **unreleased**. Existing sanitizer entry points, URL validators, schema, package dependencies and package versions are unchanged. Neither package gains an Actions SDK dependency or a dependency on the other. The two text filters do not automatically run inside existing sanitizers or factories. +The new exports are additive and **unreleased**. Both package manifests prepare preview `0.0.3`; existing sanitizer entry points, URL validators, schema and dependency versions are unchanged. Neither package gains an Actions SDK dependency or a dependency on the other. The two text filters do not automatically run inside existing sanitizers or factories. `stripAngleBracketText` matches the existing conservative character filter, including nested/unclosed markup behavior. It is neither an HTML parser nor a complete HTML sanitizer: script contents, entity text and mentions still need the owning renderer's policy. `redactJwtLikeTokens` recognizes the existing `eyJ...` three-segment shape without verifying tokens or promising exhaustive secret detection. CodeQL identified quadratic behavior in the original regex on repeated `eyJ` prefixes. The new primitive uses a linear word-run scan, verified against the original expression on bounded synthetic combinations and against long adversarial inputs. @@ -49,10 +49,10 @@ The new compatibility test recreates only the small proposed compositions from p ## Consumer rollout after package publication -1. Review this additive API change and run Action Kit quality/CI/CodeQL. Select new package versions in a separate release change; never overwrite published 0.0.2. +1. Review this additive API change and run Action Kit quality/CI/CodeQL. Both packages prepare `0.0.3`; follow the [release procedure](../RELEASING.md) and never overwrite published 0.0.2. 2. Publish the reviewed packages through the existing owner-controlled preview workflow. Do not use local links, git dependencies, tarballs or copied source as Action dependencies. 3. Create focused Build and Deploy migrations pinning the published versions. Keep `textInput(value, 'path identifier', 128)` for established input diagnostics, delegate encoding to `encodeCcv2PathSegment`, and translate shared validation failures to the existing local error. Preserve malformed-Unicode failure classification during that adapter change. 4. Replace each private angle-bracket loop and JWT regex with the new functions at the same positions in the existing compositions. Do not combine or reorder Build and Deploy sanitizers. Keep masking, empty-text behavior and summary escaping local. -5. Run full consumer tests, cross-repository event/render checks, bundle reproducibility, offline standalone-bundle tests and CI/CodeQL before merging consumer changes. Notify has no required migration for this first extraction. +5. Run full consumer tests, cross-repository event/render checks, bundle reproducibility, offline standalone-bundle tests and CI/CodeQL before merging consumer changes. Notify needs only an exact contract-version update for this extraction; its sanitizer and retry policy remain local. This PR publishes nothing, creates no tags/releases, changes no consumer dependency and calls no live providers or Sandbox services. Duplication is removed from consumer source only in the subsequent migrations after publication. diff --git a/packages/ccv2-client/CHANGELOG.md b/packages/ccv2-client/CHANGELOG.md index e42d1a3..4eb6b90 100644 --- a/packages/ccv2-client/CHANGELOG.md +++ b/packages/ccv2-client/CHANGELOG.md @@ -1,8 +1,8 @@ # ccv2-client changelog -## Unreleased +## 0.0.3 -Add `encodeCcv2PathSegment` for the existing Build/Deploy raw identifier policy, with fixed non-disclosing errors and a distinct `INVALID_PATH_ENCODING` code for malformed Unicode so Action adapters can preserve existing diagnostics. Existing URL validators and request policies are unchanged. These exports are not available in published 0.0.2; a new package release and separate consumer migrations are required. +Add `encodeCcv2PathSegment` for the existing Build/Deploy raw identifier policy, with fixed non-disclosing errors and a distinct `INVALID_PATH_ENCODING` code for malformed Unicode so Action adapters can preserve existing diagnostics. Existing URL validators and request policies are unchanged. Prepared for preview publication; consumer migrations must verify registry availability before installation. ## 0.0.2 diff --git a/packages/ccv2-client/README.md b/packages/ccv2-client/README.md index 2c19684..2f9ce05 100644 --- a/packages/ccv2-client/README.md +++ b/packages/ccv2-client/README.md @@ -36,12 +36,12 @@ Inject fetch, clock, abortable sleep, random and secret masking through `runtime Install from GitHub Packages after a supported version is published. Configure `@commercekit-tools:registry=https://npm.pkg.github.com`; local users need a classic PAT with `read:packages` in user-level configuration. Consumer Actions need package Actions read access and `GITHUB_TOKEN` with `packages: read`. See the repository authentication guide. Pin exact versions, never ranges. -Current release: source version `0.0.2`, an initial pre-1.0 integration release under the `preview` dist-tag. Verify registry availability before installation and pin `0.0.2` exactly. Stable API and coordinated consumer/Sandbox validation remain future gates. Reservation versions are unsupported. +Source version: `0.0.3`, prepared for pre-1.0 integration under the `preview` dist-tag. This manifest is not publication evidence. Verify registry availability before installation and pin `0.0.3` exactly. Stable API and coordinated consumer/Sandbox validation remain future gates. Reservation versions are unsupported. Independent package SemVer applies; stable breaking changes require a major increment. NotificationEvent schema version is separate from package version. Preserve current consumer contracts during migration. No telemetry or logging is performed. Use synthetic tests and register exact runtime secrets; pattern redaction cannot identify all secrets. -## Unreleased path primitive +## Path primitive added in 0.0.3 -The next reviewed release adds `encodeCcv2PathSegment(value: string): string` at the public root. It is **not available in published 0.0.2**. Pass a raw CCv2 identifier, not an already encoded segment. The helper rejects blank values, more than 128 UTF-16 code units, C0/C1 controls, slash/backslash/query/fragment delimiters, exact `.`/`..`, and malformed Unicode. It otherwise returns `encodeURIComponent(value)` without trimming; literal percent escapes are encoded again rather than interpreted. +Version 0.0.3 adds `encodeCcv2PathSegment(value: string): string` at the public root. It is **not available in published 0.0.2**. Pass a raw CCv2 identifier, not an already encoded segment. The helper rejects blank values, more than 128 UTF-16 code units, C0/C1 controls, slash/backslash/query/fragment delimiters, exact `.`/`..`, and malformed Unicode. It otherwise returns `encodeURIComponent(value)` without trimming; literal percent escapes are encoded again rather than interpreted. Failures throw `Ccv2TransportError` with code `INVALID_URL` for rejected segments or `INVALID_PATH_ENCODING` for malformed Unicode, with no raw identifier or stack. The separate encoding code lets consumer adapters preserve their existing error classification. Consumers retain Action input diagnostics, endpoint assembly and DTO validation. Existing URL validators and transport behavior are unchanged. See the [remaining extraction audit](../../docs/remaining-extraction-audit.md). diff --git a/packages/ccv2-client/package.json b/packages/ccv2-client/package.json index da3e62b..8d843f3 100644 --- a/packages/ccv2-client/package.json +++ b/packages/ccv2-client/package.json @@ -1,6 +1,6 @@ { "name": "@commercekit-tools/ccv2-client", - "version": "0.0.2", + "version": "0.0.3", "description": "Framework-independent CCv2 technical-user authentication and safe HTTP transport.", "license": "MIT", "type": "module", diff --git a/packages/notification-contract/CHANGELOG.md b/packages/notification-contract/CHANGELOG.md index 3bc2847..99de4ca 100644 --- a/packages/notification-contract/CHANGELOG.md +++ b/packages/notification-contract/CHANGELOG.md @@ -1,8 +1,8 @@ # notification-contract changelog -## Unreleased +## 0.0.3 -Add opt-in `stripAngleBracketText` and `redactJwtLikeTokens` primitives extracted from Build/Deploy. JWT-shaped redaction uses a linear word-run scan to avoid the copied regex's quadratic behavior on repeated prefixes. Existing sanitizers, redaction order, event factories and schema are unchanged. These exports are not available in published 0.0.2; a new package release and separate consumer migrations are required. +Add opt-in `stripAngleBracketText` and `redactJwtLikeTokens` primitives extracted from Build/Deploy. JWT-shaped redaction uses a linear word-run scan to avoid the copied regex's quadratic behavior on repeated prefixes. Existing sanitizers, redaction order, event factories and schema are unchanged. Prepared for preview publication; consumer migrations must verify registry availability before installation. ## 0.0.2 diff --git a/packages/notification-contract/README.md b/packages/notification-contract/README.md index a3199a7..1a7a899 100644 --- a/packages/notification-contract/README.md +++ b/packages/notification-contract/README.md @@ -22,13 +22,13 @@ Extraction reads only approved runner fields, never event payloads. Explicit pro Install from GitHub Packages after a supported version is published. Configure `@commercekit-tools:registry=https://npm.pkg.github.com`; local users need a classic PAT with `read:packages` in user-level configuration. Consumer Actions need package Actions read access and `GITHUB_TOKEN` with `packages: read`. See the repository authentication guide. Pin exact versions, never ranges. -Current release: source version `0.0.2`, an initial pre-1.0 integration release under the `preview` dist-tag. Verify registry availability before installation and pin `0.0.2` exactly. Stable API and coordinated consumer/Sandbox validation remain future gates. Reservation versions are unsupported. +Source version: `0.0.3`, prepared for pre-1.0 integration under the `preview` dist-tag. This manifest is not publication evidence. Verify registry availability before installation and pin `0.0.3` exactly. Stable API and coordinated consumer/Sandbox validation remain future gates. Reservation versions are unsupported. Independent package SemVer applies; stable breaking changes require a major increment. NotificationEvent schema version is separate from package version. Preserve current consumer contracts during migration. No telemetry or logging is performed. Use synthetic tests and register exact runtime secrets; pattern redaction cannot identify all secrets. -## Unreleased text primitives +## Text primitives added in 0.0.3 -The next reviewed release adds `stripAngleBracketText(value: string): string` and `redactJwtLikeTokens(value: string): string` at the public root. They are **not available in published 0.0.2**. +Version 0.0.3 adds `stripAngleBracketText(value: string): string` and `redactJwtLikeTokens(value: string): string` at the public root. They are **not available in published 0.0.2**. The first removes angle brackets and all text between each opening bracket and the next closing bracket, discarding an unclosed suffix. It neither parses HTML nor removes script text or decodes entities. The second replaces the existing Build/Deploy `eyJ`-prefixed three-segment token shape with `[REDACTED]`; it does not verify tokens or detect every credential. Both preserve unrelated characters and impose no length bound. diff --git a/packages/notification-contract/package.json b/packages/notification-contract/package.json index dc16fa8..9b184d7 100644 --- a/packages/notification-contract/package.json +++ b/packages/notification-contract/package.json @@ -1,6 +1,6 @@ { "name": "@commercekit-tools/notification-contract", - "version": "0.0.2", + "version": "0.0.3", "description": "Provider-neutral NotificationEvent v1 contracts and factories.", "license": "MIT", "type": "module",