Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0b6ede4
Complete Git-native visual CMS product flows
DMTcorp Jul 27, 2026
2a30000
Bundle editorial fonts locally
DMTcorp Jul 27, 2026
8c8ed41
Harden production dependency graph
DMTcorp Jul 27, 2026
8296c06
Use valid PNG bytes in S3 contract
DMTcorp Jul 27, 2026
0cc4806
Stabilize E2E and least-privilege R2 setup
DMTcorp Jul 27, 2026
a08e184
Make editor E2E rendering deterministic
DMTcorp Jul 28, 2026
332c08a
Make S3 release reads deterministic
DMTcorp Jul 28, 2026
2611952
Allow cross-platform visual text rasterization
DMTcorp Jul 28, 2026
ea53de0
Use current Change revision in live flow
DMTcorp Jul 28, 2026
db4f8ec
Avoid Git ref visibility race
DMTcorp Jul 28, 2026
3cf993d
Retry fresh Git ref visibility
DMTcorp Jul 28, 2026
b33f10d
Complete product acceptance flows
DMTcorp Jul 28, 2026
034e8cd
Handle unlocked staging publication on GitHub
DMTcorp Jul 28, 2026
5b00f4a
Report GitHub App rate limits as retryable
DMTcorp Jul 28, 2026
c0202d6
Close security and live acceptance gaps
DMTcorp Jul 28, 2026
ae2f958
Verify R2 assets in live acceptance
DMTcorp Jul 28, 2026
73d0e93
Persist signed upload metadata on R2
DMTcorp Jul 28, 2026
f9ccbd1
Bundle Sharp runtime for hosted adapters
DMTcorp Jul 28, 2026
44e84e0
Preserve conflict resolution CAS revision
DMTcorp Jul 28, 2026
55768a2
Precompile browser protocol validators
DMTcorp Jul 28, 2026
5b51826
Retry stale GitHub ref observations
DMTcorp Jul 28, 2026
d5aab13
Cache immutable GitHub blobs
DMTcorp Jul 28, 2026
2bc65c3
Verify immutable staging release live
DMTcorp Jul 28, 2026
d1b07ae
Prove released asset deletion safety
DMTcorp Jul 28, 2026
a92dcff
Verify localized release artifacts live
DMTcorp Jul 28, 2026
cce0dd5
Fail closed on staging pointer reads
DMTcorp Jul 28, 2026
a6e748e
Preserve CAS across conflict writes and deletes
DMTcorp Jul 28, 2026
1889d4f
Handle duplicate conflict observations safely
DMTcorp Jul 28, 2026
6408152
Bound GitHub reads during conflict analysis
DMTcorp Jul 28, 2026
51eb997
Run generated workflows on Node 24 actions
DMTcorp Jul 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,23 @@ CMS_S3_ACCESS_KEY_ID=
CMS_S3_SECRET_ACCESS_KEY=
CMS_ASSETS_BUCKET=git-native-cms-sandbox-assets
CMS_RELEASES_BUCKET=git-native-cms-sandbox-releases
CMS_STATE_BUCKET=git-native-cms-sandbox-state
CMS_PUBLIC_ASSETS_URL=
CMS_PUBLIC_RELEASES_URL=
CMS_REGISTRY_DIGEST=

# Machine actors (use independent random values, 32+ characters)
CMS_SCHEDULE_TOKEN=
CMS_MCP_TOKEN=

# Optional deployment and revalidation hooks (configure both)
CMS_DEPLOYMENT_HOOK_URL=
CMS_REVALIDATION_URL=
CMS_INTEGRATION_TOKEN=

# Optional translation provider API
CMS_TRANSLATION_PROVIDER_URL=
CMS_TRANSLATION_PROVIDER_TOKEN=

# Opt-in, read-only R2 contract smoke test (`pnpm test:integration`)
CMS_R2_SMOKE=false
Expand Down
9 changes: 9 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Default ownership for product, security and release changes.
* @mateuszgawlik

# Security-sensitive boundaries require an explicit owner review.
/packages/auth/ @mateuszgawlik
/packages/sessions/ @mateuszgawlik
/packages/permissions/ @mateuszgawlik
/packages/github/ @mateuszgawlik
/.github/workflows/ @mateuszgawlik
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Security report
url: https://github.com/DMTcorp/git-native-cms/security/advisories/new
about: Report vulnerabilities privately. Do not open a public issue.
18 changes: 18 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Change

Describe the user-facing outcome and the application command or query that owns it.

## Verification

- [ ] `pnpm check`
- [ ] Contract tests added or updated for every changed port
- [ ] Next.js and Astro behavior verified when framework integration changes
- [ ] Security, accessibility and bundle impact considered
- [ ] Documentation and Changeset updated when public behavior changes

## Architecture

- [ ] Route handlers, UI, CLI and MCP call the application layer
- [ ] No secret or installation credential is exposed to browser code or Git
- [ ] Mutations use `expectedRevision` and an idempotency key
- [ ] Deterministic outputs remain reproducible
28 changes: 28 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
time: "06:00"
timezone: Europe/Warsaw
versioning-strategy: increase
open-pull-requests-limit: 10
groups:
production-dependencies:
dependency-type: production
development-dependencies:
dependency-type: development

- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
time: "06:30"
timezone: Europe/Warsaw
groups:
actions:
patterns:
- "*"
25 changes: 25 additions & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
changelog:
exclude:
labels:
- skip-changelog
authors:
- dependabot
categories:
- title: Breaking changes
labels:
- breaking
- title: Features
labels:
- feature
- enhancement
- title: Fixes
labels:
- bug
- fix
- title: Documentation and maintenance
labels:
- documentation
- maintenance
- title: Other changes
labels:
- "*"
18 changes: 9 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ jobs:
matrix:
node: [22, 24]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node }}
cache: pnpm
Expand All @@ -34,9 +34,9 @@ jobs:
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm
Expand All @@ -55,9 +55,9 @@ jobs:
env:
CMS_CONTAINER_TESTS: "true"
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/cms-schedules.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CMS schedule executor

on:
schedule:
- cron: "*/5 * * * *"
workflow_dispatch:

concurrency:
group: cms-schedule-executor
cancel-in-progress: false

permissions:
contents: read

jobs:
execute:
runs-on: ubuntu-latest
steps:
- name: Execute due schedules
run: |
curl --fail-with-body --silent --show-error \
--request POST \
--header "authorization: Bearer $CMS_SCHEDULE_TOKEN" \
--header "content-type: application/json" \
--header "idempotency-key: schedule-${{ github.run_id }}-${{ github.run_attempt }}" \
--data '{"configVersion":1,"schemaVersion":1}' \
"$CMS_SCHEDULE_ENDPOINT"
env:
CMS_SCHEDULE_ENDPOINT: ${{ secrets.CMS_SCHEDULE_ENDPOINT }}
CMS_SCHEDULE_TOKEN: ${{ secrets.CMS_SCHEDULE_TOKEN }}
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ jobs:
changesets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v6
with:
version: 11
- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm
Expand Down
16 changes: 14 additions & 2 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,22 @@ permissions:
security-events: write

jobs:
dependency-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm audit --prod --audit-level high

codeql:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: github/codeql-action/init@v3
with:
languages: javascript-typescript
Expand All @@ -26,7 +38,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: anchore/sbom-action@v0
with:
path: .
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ test-results/
!.env.example
*.tsbuildinfo
.DS_Store
.idea/
63 changes: 61 additions & 2 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,69 @@ the result.
- Object storage stores content-addressed assets and immutable releases.
- IndexedDB stores unsynchronized patches and editor recovery state only.

## Request flow

Every entry point follows one direction:

```text
React editor / Next route / Astro route / CLI / Actions / MCP
Web API or command input
@git-native-cms/application
GitHub · content · session · storage capability ports
GitHub App · S3/R2 · filesystem adapters
```

Framework routes only mount `handle(Request, ServerContext)` or obtain a server-computed editor
view. They do not choose workflow transitions, call GitHub directly or read storage credentials.
The editor sends typed commands and renders results; permission, revision, idempotency and audit
rules live in application handlers.

## Public surfaces

- `@git-native-cms/schema` compiles deterministic component/content contracts.
- `@git-native-cms/protocol` owns versioned HTTP, preview and MCP envelopes.
- `@git-native-cms/document-model` owns RFC 6901 patches, history, merge and conflicts.
- `@git-native-cms/application/ports` is the only capability-port definition site.
- `@git-native-cms/server` exposes one Fetch API handler.
- `@git-native-cms/react`, `/next` and `/astro` render content and mount thin integrations.
- `@git-native-cms/delivery` reads filesystem, Git, preview or immutable CDN releases.
- `@git-native-cms/mcp` and `cms` reuse application permissions and confirmation contracts.

## Mutation invariants

Mutations carry an idempotency key and the exact expected Git/pointer revision. Domain IDs use a
prefixed ULID shape; release IDs derive from SHA-256 of the canonical manifest. Timestamps are UTC
ISO-8601. Git writes and environment pointers use compare-and-swap. Retryable external hooks
receive deterministic keys.

Preview sessions, OAuth tokens, installation credentials, S3 credentials and confirmation tokens
are server-only. Cookies are encrypted, rotated, `Secure`, `HttpOnly` and CSRF-bound.

## Git and release workflow

A Change starts from Production `main`. Review opens a pull request, approval requires an
independent reviewer, and adding to Staging squash-merges with `Change-ID` before deleting the
branch. Staging promotion uses a merge commit into `main`, forward-syncs Staging, builds a
reproducible immutable release and atomically moves the pointer. Rollback moves the pointer before
opening its audit revert pull request.

Before the squash merge, the application compares the original base, the Change and current
Staging for every document, including document creation/deletion. Concurrent edits become
RFC 6901 field conflicts. A resolution command requires an explicit `change` or `staging` choice
for every conflict, carries the Change revision, preserves non-conflicting Staging updates, records
the new semantic base and resets an existing approval. The resolved result must therefore be
reviewed again before Staging can accept it.

## Compatibility

The supported server runtimes are Node.js 22.12+ and Node.js 24. Pure packages use Web APIs and
are tested in browser and worker-like environments. Full Astro CMS support requires SSR.

See [ADR-0001](./docs/adr/0001-ports-and-adapters.md) and
[ADR-0002](./docs/adr/0002-deterministic-releases.md).
See [ADR-0001](./docs/adr/0001-ports-and-adapters.md),
[ADR-0002](./docs/adr/0002-deterministic-releases.md) and
[ADR-0003](./docs/adr/0003-preview-assets-and-team-capabilities.md), and
[ADR-0004](./docs/adr/0004-semantic-conflict-resolution.md).
24 changes: 21 additions & 3 deletions apps/docs/astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,34 @@ export default defineConfig({
{ icon: "github", label: "GitHub", href: "https://github.com/DMTcorp/git-native-cms" },
],
sidebar: [
{ label: "Start", items: ["index", "getting-started"] },
{ label: "Start", items: ["index", "getting-started", "troubleshooting"] },
{
label: "Core concepts",
items: ["architecture", "changes-and-publishing", "content-modeling"],
items: [
"architecture",
"changes-and-publishing",
"content-modeling",
"fields-and-sections",
"permissions",
],
},
{
label: "Integrations",
items: ["nextjs", "astro", "astro-static", "mcp", "adapters"],
},
{ label: "Operations", items: ["security", "doctor-and-upgrades", "sandbox"] },
{
label: "Operations",
items: [
"assets",
"delivery",
"seo-localization-search",
"scheduling-integrations",
"security",
"doctor-and-upgrades",
"sandbox",
"acceptance",
],
},
],
}),
],
Expand Down
Loading
Loading