Add operational docs for release workflow
This commit is contained in:
@@ -187,3 +187,6 @@ See [docs/format.md](docs/format.md) and
|
||||
[docs/client-integration.md](docs/client-integration.md).
|
||||
For Codex and Claude Code MCP setup, see [docs/agent-setup.md](docs/agent-setup.md).
|
||||
For the runtime key payload contract, see [docs/launcher-contract.md](docs/launcher-contract.md).
|
||||
For release steps, see [docs/release-workflow.md](docs/release-workflow.md).
|
||||
For key rotation policy, see [docs/key-rotation.md](docs/key-rotation.md).
|
||||
For legacy pack migration, see [docs/migration.md](docs/migration.md).
|
||||
|
||||
72
docs/key-rotation.md
Normal file
72
docs/key-rotation.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Key rotation
|
||||
|
||||
`m2pack-secure` supports archive-level `key_id` so releases can move away from a
|
||||
single permanent content key.
|
||||
|
||||
## Why rotate
|
||||
|
||||
Rotate when:
|
||||
|
||||
- a content key may have leaked
|
||||
- a signing key may have leaked
|
||||
- you want to expire old launcher material
|
||||
- you want to separate major release lines
|
||||
- you change pack validation or loader policy
|
||||
|
||||
## Current model
|
||||
|
||||
- each archive stores a `key_id` in its header
|
||||
- the client chooses the verifier public key by `key_id`
|
||||
- the runtime master key must be delivered with the same `key_id`
|
||||
- `.m2p` loading fails if the archive `key_id` and runtime `key_id` do not match
|
||||
|
||||
## Recommended policy
|
||||
|
||||
- keep `key_id` monotonic
|
||||
- reserve one `key_id` per release line or rotation event
|
||||
- never reuse an old `key_id` for different secret material
|
||||
- keep old public verification keys only as long as you need to support those releases
|
||||
- remove stale keys from the client once old archives are no longer supported
|
||||
|
||||
## Rotation procedure
|
||||
|
||||
1. Generate a new `master.key`.
|
||||
2. Generate a new signing keypair if needed.
|
||||
3. Assign a new `key_id`.
|
||||
4. Rebuild archives with `--key-id <new-id>`.
|
||||
5. Export a new `M2PackKeys.h` for the client.
|
||||
6. Export a new runtime key payload for the launcher.
|
||||
7. Ship client, launcher, and `.m2p` together.
|
||||
8. Retire old runtime material after rollout is complete.
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
./build/m2pack keygen --out-dir keys-2026-05
|
||||
|
||||
./build/m2pack build \
|
||||
--input /srv/build/client-root \
|
||||
--output out/root.m2p \
|
||||
--key keys-2026-05/master.key \
|
||||
--sign-secret-key keys-2026-05/signing.key \
|
||||
--key-id 4
|
||||
|
||||
./build/m2pack export-client-config \
|
||||
--key keys-2026-05/master.key \
|
||||
--public-key keys-2026-05/signing.pub \
|
||||
--key-id 4 \
|
||||
--output /path/to/m2dev-client-src/src/PackLib/M2PackKeys.h
|
||||
|
||||
./build/m2pack export-runtime-key \
|
||||
--key keys-2026-05/master.key \
|
||||
--public-key keys-2026-05/signing.pub \
|
||||
--key-id 4 \
|
||||
--format blob \
|
||||
--output out/runtime-key.bin
|
||||
```
|
||||
|
||||
## Operational note
|
||||
|
||||
If you need overlapping support for multiple release lines, extend the client
|
||||
header with multiple verifier slots and keep launcher delivery strict: one
|
||||
runtime master key per active process, matching the archive `key_id`.
|
||||
65
docs/migration.md
Normal file
65
docs/migration.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Migration from legacy packs
|
||||
|
||||
This project is meant to replace legacy `.pck` or EterPack-style content
|
||||
delivery gradually, not through a single risky cutover.
|
||||
|
||||
## Target state
|
||||
|
||||
- Linux builds produce `.m2p`
|
||||
- the client loads `.m2p` first
|
||||
- runtime master key delivery is required
|
||||
- silent fallback to legacy packs is disabled in production
|
||||
|
||||
## Suggested migration phases
|
||||
|
||||
### Phase 1: parallel loader
|
||||
|
||||
- keep the legacy loader in the client
|
||||
- add `.m2p` support beside it
|
||||
- verify the new loader against real content sets
|
||||
- keep fallback only in development if needed
|
||||
|
||||
### Phase 2: pipeline validation
|
||||
|
||||
- build `.m2p` from the same source tree as legacy packs
|
||||
- run `verify` for every archive
|
||||
- run `diff` between the source tree and `.m2p`
|
||||
- compare in-game behavior between legacy and `.m2p`
|
||||
|
||||
### Phase 3: runtime delivery
|
||||
|
||||
- stop embedding a real content key in the client
|
||||
- deliver the runtime key through launcher, environment, or mapping
|
||||
- verify startup failure behavior when the runtime key is missing
|
||||
|
||||
### Phase 4: production cutover
|
||||
|
||||
- package only `.m2p` for release clients
|
||||
- disable silent fallback to legacy packs
|
||||
- remove stale pack generation from release CI
|
||||
- keep extract/debug tools only for internal use
|
||||
|
||||
## Recommended checks
|
||||
|
||||
- duplicate normalized paths
|
||||
- invalid relative paths
|
||||
- case-collision problems on Windows
|
||||
- decompression failures
|
||||
- manifest signature failures
|
||||
- key mismatch by `key_id`
|
||||
|
||||
## Practical migration loop
|
||||
|
||||
1. Pick one legacy pack group.
|
||||
2. Rebuild it as `.m2p`.
|
||||
3. Verify it.
|
||||
4. Diff it against the source tree.
|
||||
5. Boot the client with runtime keys.
|
||||
6. Validate asset loads in logs and in-game.
|
||||
7. Move to the next pack group.
|
||||
|
||||
## Risk notes
|
||||
|
||||
- Do not mix silent fallback with production security claims.
|
||||
- Do not ship a client that accepts `.m2p` without runtime key enforcement.
|
||||
- Do not keep real secret keys inside the repository.
|
||||
86
docs/release-workflow.md
Normal file
86
docs/release-workflow.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Release workflow
|
||||
|
||||
This is the recommended end-to-end release flow for `m2pack-secure`.
|
||||
|
||||
The goal is to keep archive creation on Linux, keep signing keys off developer
|
||||
workstations when possible, and make the Windows client consume only runtime
|
||||
delivery material.
|
||||
|
||||
## Inputs
|
||||
|
||||
- client asset tree
|
||||
- `master.key`
|
||||
- `signing.key`
|
||||
- `signing.pub`
|
||||
- target `key_id`
|
||||
|
||||
## Output artifacts
|
||||
|
||||
- one or more `.m2p` archives
|
||||
- generated `M2PackKeys.h`
|
||||
- runtime key payload for the launcher
|
||||
- release manifest and validation logs
|
||||
|
||||
## Minimal release flow
|
||||
|
||||
1. Generate or select the active content key set.
|
||||
2. Build the archive with the intended `key_id`.
|
||||
3. Verify the archive with the signing public key and content key.
|
||||
4. Diff the archive against the source tree to catch packing mistakes.
|
||||
5. Export `M2PackKeys.h` for the client source tree.
|
||||
6. Export the runtime key payload for the launcher.
|
||||
7. Build the Windows client against the generated header.
|
||||
8. Ship `.m2p` plus the client and launcher together.
|
||||
|
||||
## Example
|
||||
|
||||
```bash
|
||||
./build/m2pack build \
|
||||
--input /srv/build/client-root \
|
||||
--output out/root.m2p \
|
||||
--key keys/master.key \
|
||||
--sign-secret-key keys/signing.key \
|
||||
--key-id 3 \
|
||||
--json
|
||||
|
||||
./build/m2pack verify \
|
||||
--archive out/root.m2p \
|
||||
--public-key keys/signing.pub \
|
||||
--key keys/master.key \
|
||||
--json
|
||||
|
||||
./build/m2pack diff \
|
||||
--left /srv/build/client-root \
|
||||
--right out/root.m2p \
|
||||
--json
|
||||
|
||||
./build/m2pack export-client-config \
|
||||
--key keys/master.key \
|
||||
--public-key keys/signing.pub \
|
||||
--key-id 3 \
|
||||
--output /path/to/m2dev-client-src/src/PackLib/M2PackKeys.h \
|
||||
--json
|
||||
|
||||
./build/m2pack export-runtime-key \
|
||||
--key keys/master.key \
|
||||
--public-key keys/signing.pub \
|
||||
--key-id 3 \
|
||||
--format json \
|
||||
--output out/runtime-key.json \
|
||||
--json
|
||||
```
|
||||
|
||||
## CI recommendations
|
||||
|
||||
- Run archive builds on Linux only.
|
||||
- Keep `signing.key` in CI secrets or on a dedicated release box.
|
||||
- Treat `master.key` as release secret material, not as source code.
|
||||
- Archive and retain `verify` and `diff` outputs for each release.
|
||||
- Fail the pipeline if `verify` fails or `diff` reports unexpected changes.
|
||||
|
||||
## Production posture
|
||||
|
||||
- The client should embed only verifier material and metadata.
|
||||
- The launcher should provide the runtime master key.
|
||||
- If `.m2p` exists and runtime key delivery fails, startup should fail hard.
|
||||
- Do not silently fall back to legacy packs in production.
|
||||
Reference in New Issue
Block a user