390 lines
6.3 KiB
Markdown
390 lines
6.3 KiB
Markdown
Great, let’s do this **concretely and end-to-end**, but still faithful to the specs you’ve been shaping. I’ll walk a **single artifact** all the way through its lifecycle:
|
||
|
||
* creation
|
||
* witnessing (certificate case)
|
||
* indexing
|
||
* snapshotting
|
||
* eviction from local storage
|
||
* later rehydration
|
||
* reuse in a new program
|
||
|
||
I’ll label **what is normative** vs **implementation choice**, and I’ll keep the mental model consistent: **blocks are physical, artifacts are semantic**.
|
||
|
||
---
|
||
|
||
# End-to-End Artifact Lifecycle Walkthrough
|
||
|
||
We’ll use a **certificate artifact** because it exercises *authority*, *witnessing*, and *reuse*.
|
||
|
||
Assume we are on a **personal domain** `alice.personal`, on an ASL-HOST.
|
||
|
||
---
|
||
|
||
## Phase 0 – Initial state (before anything happens)
|
||
|
||
On disk:
|
||
|
||
```
|
||
/asl/domains/alice.personal/
|
||
├── blocks/
|
||
│ ├── open/
|
||
│ └── sealed/
|
||
├── index/
|
||
├── log/
|
||
├── snapshots/
|
||
└── meta/
|
||
└── dam/
|
||
```
|
||
|
||
Current snapshot:
|
||
|
||
```
|
||
alice.personal@42
|
||
```
|
||
|
||
Authority:
|
||
|
||
* DAM says `self-authority`
|
||
* Host holds Alice’s private key
|
||
* Host is **Active**
|
||
|
||
---
|
||
|
||
## Phase 1 – Artifact creation (certificate is generated)
|
||
|
||
### What happens conceptually
|
||
|
||
A **PEL program** is run that generates a certificate:
|
||
|
||
* Input: key material, policy parameters
|
||
* Output: certificate bytes
|
||
|
||
This is *just data* at this stage.
|
||
|
||
---
|
||
|
||
### On disk: block writing (physical layer)
|
||
|
||
1. ASL allocates an **open block**:
|
||
|
||
```
|
||
blocks/open/blk_tmp_7f3a.tmp
|
||
```
|
||
|
||
2. Certificate bytes are appended to the open block.
|
||
|
||
3. The artifact bytes occupy:
|
||
|
||
```
|
||
offset = 8192
|
||
length = 1432
|
||
```
|
||
|
||
At this moment:
|
||
|
||
* No artifact exists yet (semantically)
|
||
* Bytes are **not visible**
|
||
* Crash here is allowed
|
||
|
||
---
|
||
|
||
### Block sealing (normative)
|
||
|
||
4. Block is sealed:
|
||
|
||
```
|
||
block_id = H(block_bytes)
|
||
```
|
||
|
||
File moved to:
|
||
|
||
```
|
||
blocks/sealed/7f/7f3a9c...blk
|
||
```
|
||
|
||
**Invariant satisfied:** sealed blocks are immutable.
|
||
|
||
---
|
||
|
||
## Phase 2 – Artifact becomes real (indexing)
|
||
|
||
### Artifact identity
|
||
|
||
Artifact key is computed from:
|
||
|
||
```
|
||
H(certificate_bytes + type_tag + metadata)
|
||
```
|
||
|
||
Example:
|
||
|
||
```
|
||
artifact_key = a9c4…
|
||
```
|
||
|
||
---
|
||
|
||
### Index entry written
|
||
|
||
An index entry is appended to an **open index segment**:
|
||
|
||
```
|
||
index/shard-012/segment-0042.idx (open)
|
||
```
|
||
|
||
Entry:
|
||
|
||
```
|
||
ArtifactKey → (BlockID, offset, length)
|
||
type_tag = cert.x509
|
||
```
|
||
|
||
Still **not visible**.
|
||
|
||
---
|
||
|
||
### Log append (normative visibility point)
|
||
|
||
A log record is appended:
|
||
|
||
```
|
||
log-0000000000001200.asl
|
||
```
|
||
|
||
Record:
|
||
|
||
```
|
||
ADD_INDEX_ENTRY artifact_key=a9c4… segment=0042
|
||
```
|
||
|
||
Then:
|
||
|
||
```
|
||
SEAL_SEGMENT segment=0042
|
||
```
|
||
|
||
**Now the artifact exists.**
|
||
|
||
---
|
||
|
||
## Phase 3 – Snapshot & witnessing
|
||
|
||
### Snapshot creation
|
||
|
||
A snapshot is emitted:
|
||
|
||
```
|
||
alice.personal@43
|
||
```
|
||
|
||
Snapshot pins:
|
||
|
||
* index segment 0042
|
||
* block 7f3a…
|
||
|
||
Snapshot manifest includes:
|
||
|
||
```
|
||
authority:
|
||
domain: alice.personal
|
||
key: alice-root-key
|
||
```
|
||
|
||
---
|
||
|
||
### Witnessing from elsewhere (certificate use case)
|
||
|
||
Now the **certificate is taken aboard** by another domain, say:
|
||
|
||
```
|
||
common
|
||
```
|
||
|
||
How?
|
||
|
||
1. The certificate artifact is **published** (policy allows this)
|
||
2. `common` imports the artifact:
|
||
|
||
* artifact bytes are fetched (or referenced)
|
||
* artifact key is preserved
|
||
3. A **cross-domain reference** is indexed in `common`
|
||
|
||
No copying is required if blocks are addressable, but often they are copied.
|
||
|
||
Witnessing here means:
|
||
|
||
> The certificate is now **provably present in two domains**, each with their own snapshot history.
|
||
|
||
---
|
||
|
||
## Phase 4 – Time passes (artifact becomes cold)
|
||
|
||
A week passes.
|
||
|
||
A **local retention policy** runs (implementation choice, but policy-guided).
|
||
|
||
### GC decision (normative constraints)
|
||
|
||
The artifact:
|
||
|
||
* is sealed
|
||
* is referenced by snapshot `@43`
|
||
* is not referenced by CURRENT workflows
|
||
|
||
Policy allows **cold eviction** if:
|
||
|
||
* snapshot still exists
|
||
* artifact can be re-fetched from trusted domains
|
||
|
||
So…
|
||
|
||
---
|
||
|
||
### Block eviction (implementation choice)
|
||
|
||
Local block file is removed:
|
||
|
||
```
|
||
blocks/sealed/7f/7f3a9c...blk ← deleted
|
||
```
|
||
|
||
But:
|
||
|
||
* index entry remains
|
||
* snapshot remains
|
||
* artifact is still **logically present**
|
||
|
||
This is allowed because:
|
||
|
||
> **ASL defines availability separately from existence.**
|
||
|
||
---
|
||
|
||
## Phase 5 – Artifact is needed again
|
||
|
||
Later, a new PEL program runs:
|
||
|
||
* Input: certificate artifact `a9c4…`
|
||
* Purpose: sign something new
|
||
|
||
### Artifact lookup
|
||
|
||
1. Index lookup finds:
|
||
|
||
```
|
||
ArtifactKey → (BlockID, offset, length)
|
||
```
|
||
2. Block is missing locally.
|
||
|
||
---
|
||
|
||
### Rehydration (normative + policy)
|
||
|
||
ASL-HOST:
|
||
|
||
1. Consults **domain policy**
|
||
2. Finds trusted source:
|
||
|
||
* `common`
|
||
* or a personal mirror
|
||
3. Fetches block by `BlockID`
|
||
|
||
Block is restored to:
|
||
|
||
```
|
||
blocks/sealed/7f/7f3a9c...blk
|
||
```
|
||
|
||
**Block hash verified.**
|
||
|
||
---
|
||
|
||
## Phase 6 – Artifact reused in a new program
|
||
|
||
The certificate bytes are read from the block.
|
||
|
||
A new PEL program runs:
|
||
|
||
* Inputs:
|
||
|
||
* certificate artifact `a9c4…`
|
||
* new data
|
||
* Outputs:
|
||
|
||
* new artifact(s)
|
||
* new PER
|
||
|
||
These outputs repeat the **same lifecycle**.
|
||
|
||
---
|
||
|
||
## Phase 7 – Index & snapshot continuity
|
||
|
||
Now:
|
||
|
||
* Snapshot `@44` references:
|
||
|
||
* old certificate
|
||
* new artifacts
|
||
* Old artifact remains immutable
|
||
* Provenance is intact
|
||
|
||
At no point did we:
|
||
|
||
* rewrite bytes
|
||
* change meaning
|
||
* trust runtime state
|
||
|
||
---
|
||
|
||
## What was witnessed, exactly?
|
||
|
||
Three things were witnessed, independently:
|
||
|
||
1. **Bytes** (block hash)
|
||
2. **Meaning** (artifact key → index)
|
||
3. **Authority** (snapshot + DAM + signatures)
|
||
|
||
This is why the system holds together.
|
||
|
||
---
|
||
|
||
## Why this works for *everything*
|
||
|
||
This same flow works for:
|
||
|
||
* certificates
|
||
* home directory tarballs
|
||
* shell command outputs
|
||
* TGK edges
|
||
* PERs
|
||
* witness rotation artifacts
|
||
|
||
Nothing special happens for “important” artifacts.
|
||
|
||
---
|
||
|
||
## The key invariants you just saw
|
||
|
||
1. **Artifacts never move**
|
||
2. **Blocks may come and go**
|
||
3. **Snapshots pin meaning, not bytes**
|
||
4. **Witnessing is just another artifact**
|
||
5. **Time does not weaken correctness**
|
||
|
||
---
|
||
|
||
## One sentence to take away
|
||
|
||
> An artifact can disappear from disk, reappear a year later, and still mean exactly the same thing.
|
||
|
||
If you want next, we can:
|
||
|
||
* walk the **same artifact across two personal machines**
|
||
* show **what breaks if someone cheats**
|
||
* map this onto **ZFS send/receive**
|
||
* or show **how PEL receipts stitch all this together**
|
||
|
||
You’re now fully “above the filesystem” — exactly where you wanted to be.
|
||
|