Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a51b357
feat(runtime): dKMS/dDRM/chain/marketplace foundation on the ESP subs…
irzhywau Aug 7, 2026
47e4e36
feat(capsules): dKMS/dDRM provider, crypto, and marketplace capsules
irzhywau Aug 7, 2026
2be649e
feat(shell): owned-asset commerce UX in Home
irzhywau Aug 7, 2026
5d9eb46
ci: dkms verification gates and dev harnesses
irzhywau Aug 7, 2026
e2cc422
docs: dKMS/dDRM/marketplace documentation and glossary
irzhywau Aug 7, 2026
183113e
feat(docker): update Dockerfile and docker-compose for dKMS node conf…
irzhywau Aug 7, 2026
1502db9
docs(specs): roadmap coverage baseline and gap bulk plan for 0.7-dev
irzhywau Aug 7, 2026
943c10d
fix(dkms): remediate reviewed dKMS security findings (DKMS-1..8)
irzhywau Aug 12, 2026
353fa15
test(gateway): deterministic settlement for the elastos-server flake …
irzhywau Aug 12, 2026
2b73ac7
fix(esp): close marketplace buy/trade content-id seams (ESP-1, ESP-2)
irzhywau Aug 12, 2026
0b43da8
feat(auth): offline migrate-audit-chain for pre-hardening data roots
irzhywau Aug 13, 2026
58ce2bc
build(dkms): drop unused v1 seal test helper
irzhywau Aug 13, 2026
7e2d7cd
fix: troubleshooting runtime provisionning alongside dkms (on docker)
irzhywau Aug 14, 2026
6d2e908
feat: Add elacity-player and ddrm-viewer capsules for protected media…
irzhywau Aug 14, 2026
c5aed9d
fix: add new asset creation interface and update capsule entry point
irzhywau Aug 14, 2026
5797447
fix(dkms): open protected dDRM assets in the ESP shell via connector-…
irzhywau Aug 15, 2026
3b7a48b
fix(logging): implement leveled logging for dkms-authority and dkms-c…
irzhywau Aug 17, 2026
ffea599
fix(esp): repair the Create → mint → open dDRM asset flow
irzhywau Aug 17, 2026
e148218
fix(ci): repair the verify-ci gate after the Create-portal wallet rewire
irzhywau Aug 17, 2026
27d85c6
feat(logger): add elastos-logger — a 5-level library with pluggable s…
irzhywau Aug 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .codex/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[shell_environment_policy]
inherit = "core"

[shell_environment_policy.set]
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS = "1"
112 changes: 111 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@ name: CI

on:
push:
branches: [main]
# `main` is the live line. The work-branch patterns are included so we can run the
# full gate on our own work in isolation (this entry lives only on the branch; it
# does NOT affect main or other branches until/unless it is merged). Drop the
# non-`main` patterns at merge time.
branches: [main, feat/**, upstream/**, review/**]
pull_request:
branches: [main]
# Manual trigger so a feature branch can be put through the full Linux gate
# (incl. the Linux-only carrier smoke in `just verify`) before merge.
workflow_dispatch:

env:
CARGO_TERM_COLOR: always
Expand Down Expand Up @@ -38,6 +45,11 @@ jobs:
- name: cargo check
working-directory: elastos
run: cargo check --workspace
# Type-check the network-gated live-buy test so a rename can't silently rot the operator's
# only live tool (it stays #[ignore]d + feature-off in the gate; this never runs it). S45 F3.
- name: cargo check (live-chain test)
working-directory: elastos
run: cargo check -p elastos-server --features live-chain --tests

test:
name: Test
Expand All @@ -53,6 +65,13 @@ jobs:
run: cargo test --workspace
# Network-sensitive tests are #[ignore] and won't run.
# Run them explicitly with: cargo test --workspace -- --ignored
- name: cargo test (dev-modes lane)
working-directory: elastos
# The money-path construction ratchets (S43 typed BuyError, the S46 prepare-leg
# deadline, chain-mock buys) are `#[cfg(feature = "dev-modes")]` — without this lane
# the gate never compiles them, and a ratchet outside the gate cannot ratchet
# (council S46 guardian F3). Lib-only; shares the workspace build cache.
run: cargo test -p elastos-server --lib --features dev-modes

build-release:
name: Build Release (x86_64)
Expand All @@ -66,3 +85,94 @@ jobs:
- name: cargo build --release
working-directory: elastos
run: cargo build --workspace --release

# The canonical gate on Linux, MINUS the Carrier-network setup smoke: alignment-check +
# command smoke + candidate-command-audit + fmt/clippy/test (elastos workspace) + the dDRM
# capsule build+test (verify-capsules). This turns "manually covered" into "green on a clean
# runner". The `local-carrier-setup-smoke` step is excluded here because it fetches the
# net-provider artifact over Elastos Carrier, which a stock GitHub runner cannot reach — run
# the full `just verify` on a Carrier-capable Linux box / self-hosted runner before merge.
# RUSTFLAGS=-D warnings is inherited from `env` above.
verify:
name: Verify (Linux CI gate)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
with:
workspaces: |
elastos
capsules/decrypt-provider
capsules/ddrm-envelope
scripts/dev/ddrm-media-authority
- uses: extractions/setup-just@v2
- name: Install ripgrep (required by alignment-check; not preinstalled on the runner)
run: sudo apt-get update && sudo apt-get install -y ripgrep
- name: just verify-ci
run: just verify-ci

# Isolated, fast signal for the protected-content capsule crates that live OUTSIDE
# the elastos workspace (so the `check`/`test` jobs and `cargo --workspace` never
# reach them): the watermark codec, the grant-digest envelope, the media-authority.
# Independent of the carrier smoke, so a flaky/heavy smoke run never masks a capsule
# regression. Build+test only (these crates still carry pre-existing clippy debt).
capsules:
name: dDRM Capsule Gate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: |
capsules/decrypt-provider
capsules/ddrm-envelope
scripts/dev/ddrm-media-authority
- uses: extractions/setup-just@v2
- name: just verify-capsules
run: just verify-capsules

# Pre-mainnet deploy invariant (fix-pack ②): a PRODUCTION dkms-authority node must be a release
# build with DEFAULT features — the legacy unsigned-receipt path (`legacy-receipt-authz`) and the
# `dev-modes` opt-in that pulls it in must NEVER ship. The crate enforces this with a
# `compile_error!` keyed on a release build (no `debug_assertions`); this job asserts BOTH
# directions so the guard can't silently rot. See `docs/DEPLOY_CHECKLIST.md`.
# `dkms-authority` lives OUTSIDE the elastos workspace, so the other jobs never reach it.
dkms-release-invariant:
name: dKMS Release Invariant (no dev-modes/legacy)
runs-on: ubuntu-latest
# Assert the FEATURE invariant only; do not let unrelated pre-existing rustc warnings in this
# out-of-workspace crate mask it (the rest of CI keeps -D warnings).
env:
RUSTFLAGS: ""
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: capsules/dkms-authority
- name: Release build with DEFAULT features must succeed (no legacy path compiled)
run: cargo build --release --manifest-path capsules/dkms-authority/Cargo.toml
- name: Release build with legacy-receipt-authz must FAIL closed (compile guard)
run: |
if out=$(cargo build --release --manifest-path capsules/dkms-authority/Cargo.toml --features legacy-receipt-authz 2>&1); then
echo "::error::release build ACCEPTED legacy-receipt-authz — the release-invariant guard is missing"
exit 1
fi
echo "$out" | grep -q "release build must not enable" || {
echo "::error::release build failed, but NOT via the release-invariant guard:"; echo "$out"; exit 1;
}
echo "ok: release + legacy-receipt-authz rejected at compile time"
- name: Release build with dev-modes must FAIL closed (compile guard)
run: |
if out=$(cargo build --release --manifest-path capsules/dkms-authority/Cargo.toml --features dev-modes 2>&1); then
echo "::error::release build ACCEPTED dev-modes — the release-invariant guard is missing"
exit 1
fi
echo "$out" | grep -q "release build must not enable" || {
echo "::error::release build failed, but NOT via the release-invariant guard:"; echo "$out"; exit 1;
}
echo "ok: release + dev-modes rejected at compile time"
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ elastos/storage/
artifacts/
artifacts-aarch64/

# Local scratch build tree (vendored linux kernel source, cargo output, etc.)
build/

# Secrets and credentials
.env
*.pem
Expand All @@ -53,9 +56,8 @@ credentials.json
# Cache
.elastos/

# Claude Code (user-specific settings; shared skills are tracked)
.claude/*
!.claude/skills/
# Claude Code (user-specific settings)
.claude/

# External dependencies
puter-upstream/
Expand Down
21 changes: 0 additions & 21 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,6 @@ lives in [state.md](state.md), and open work lives in [TASKS.md](TASKS.md).
- Always report remote divergence. A local branch being green is not the same as
`elacity/<branch>` being up to date.

## Creating Work Branches

New feature or bugfix branches start from an `upstream/XX-dev` integration
branch (e.g. `upstream/0.6-dev`) — never silently from `main` or from whatever
branch happens to be checked out. The user chooses the base; do not pick it
yourself:

- Run `git fetch origin --prune`, then list `upstream/*-dev` lines and active
`feat/*`/`fix/*` branches before proposing bases.
- Ask the user which base to start from, offering each `upstream/XX-dev`
(newest recommended) plus "an existing working branch" for work that depends
on another in-flight branch. Ask even when only one dev line exists.
- If the chosen base is a working branch rather than `upstream/XX-dev`, warn
immediately: the new branch must merge back only after (or together with)
its parent, merging it into `upstream/XX-dev` may conflict with the parent's
changes, and it needs a rebase if the parent moves.
- Name branches `feat/<slug>` or `fix/<slug>`; do not push or set upstream
tracking until asked.

Canonical workflow: [.claude/skills/branching-strategy/SKILL.md](.claude/skills/branching-strategy/SKILL.md).

## Branch Lifecycle

Before creating, deleting, merging, or publishing branches, produce a short
Expand Down
47 changes: 47 additions & 0 deletions DEBUG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,37 @@ work log.
- Durable architecture guidance belongs in `docs/`.
- Stable local-debugging invariants belong here.

## Logging

The gateway builds its log filter in `elastos/crates/elastos-server/src/main.rs`
from the standard `RUST_LOG` environment variable on top of a hard `elastos=info`
baseline. `RUST_LOG` takes tracing directives (`target=level`, comma-separated);
the most specific matching target wins, so you can tune one subsystem without
touching the rest.

```bash
# More detail from one area:
RUST_LOG="elastos_server::api=debug"

# Silence one noisy target while keeping every other WARN:
RUST_LOG="elastos::provider::latency=error"

# Combine directives:
RUST_LOG="elastos::provider::latency=error,elastos_server::api=debug"
```

Some targets exist specifically so they can be tuned this way. Example:
`elastos::provider::latency` is a tripwire that WARNs whenever a provider round
trip exceeds 150ms. Once a principal root is protected, object-provider event
reads legitimately cost ~200-300ms (the data key is deliberately re-derived per
read — no caching, by security policy), so the tripwire fires on every Home
realtime poll. Filtering that target to `error` is the intended way to quiet
it; do not raise the threshold or cache the key.

Set `RUST_LOG` in the shell that launches the gateway, or for VS Code debugging
in the `options.env` of the gateway bring-up task in `.vscode/tasks.json` (the
gateway passes its env down to every provider it execs).

## Provider Bridge Invariant

Provider request/response pipes must be cancellation-safe. If an HTTP caller
Expand All @@ -41,6 +72,22 @@ still drain exactly one response line before the next request can read from the
provider. Otherwise a later request can consume stale provider output from an
earlier request.

## Viewer Session Lifecycle Invariant

A viewer session (object or media) pins a gateway-spawned authority subprocess
chain (for a quorum open: `ddrm-media-authority --quorum` → `decrypt-provider`
+ `key-provider`). Those processes outliving the viewer is a bug in one of the
three release paths, not expected behavior: (1) the explicit close route
(`POST /api/viewers/:viewer/{object,media}/:session/close`), fired by the
viewer capsule on `pagehide` and by the Home shell on window close; (2) the
60s `session_lifecycle` sweeper, which releases expired sessions on the clock;
(3) the store's lazy sweep on lookup/admission. When debugging lingering
`ddrm-media-authority` / `decrypt-provider` processes, check those paths in
that order before suspecting the reap itself — session drops must also honor
the deferred-drop contract (reaps run after the store lock releases, never
under it). New session kinds must register with the `SessionLifecycle` trait
in `api/session_lifecycle.rs`; a registered-kinds test pins the registry.

## Provider Deploy Invariant

When a standalone provider changes, deployed Home or app assets are not enough.
Expand Down
Loading
Loading