authkeep-server
Issuer-side operations for publishing SIG feeds.
The authkeep-server crate provides issuer-side operations for creating and managing SIG feeds. It handles metadata generation, DID document construction, feed initialization, key management, and event appending with built-in file locking and validation. This crate depends on both authkeep-core and authkeep-jose.
Key Functions
build_metadata
pub fn build_metadata(domain: &str) -> OreMetadata
Constructs an OreMetadata document for the given domain. Generates the standard well-known URIs for the JWKS and events endpoints based on the domain, and sets the spec version to sig/0.1.
build_did_document
pub fn build_did_document(domain: &str, jwks: &Jwks) -> Value
Generates a did:web DID document for the issuer. The document includes verification methods derived from the provided JWKS, linking the issuer’s domain identity to their signing keys. The DID document follows the W3C DID Core specification.
init_public_issuer
pub fn init_public_issuer(
out_dir: &Path,
domain: &str,
jwks: &Jwks,
) -> Result<()>
Initializes a complete public issuer directory structure. Creates the .well-known/ directory and writes the sig-metadata.json, did.json, sig-jwks.json, and an empty sig-events.jsonl file. This is the starting point for a new issuer.
add_signing_key_to_issuer
pub fn add_signing_key_to_issuer(
issuer_dir: &Path,
domain: &str,
jwk: Jwk,
) -> Result<()>
Adds a new public key to an existing issuer’s JWKS and regenerates the DID document. This supports key rotation by allowing multiple active signing keys. The JWKS file is updated atomically.
append_signed_event
pub fn append_signed_event(
events_path: &Path,
payload: &mut Value,
signing_key: &SigningKey,
kid: &str,
public_feed: bool,
) -> Result<u64>
Appends a new signed event to the feed’s events file. This function handles the complete event lifecycle:
- File locking — Acquires an exclusive file lock on the events file to prevent concurrent write corruption. The lock is held for the duration of the operation and released automatically.
- Sequence assignment — Reads the current feed to determine the next sequence number and auto-assigns it to the event payload. Sequence numbers are monotonically increasing starting from 1.
- Duplicate rejection — Checks the
event_idagainst all existing events in the feed. If a duplicateevent_idis detected, the operation is rejected with an error. - Validation — Passes the payload through
authkeep-core’svalidate_eventto enforce specification rules before signing. - Signing — Signs the payload using
authkeep-jose’ssign_payloadwith the provided signing key and key ID. - Appending — Writes the JWS envelope as a new line in the JSONL events file.
Returns the assigned sequence number on success.
make_upsert_payload
pub fn make_upsert_payload(
event_id: &str,
issuer_did: &str,
subject: &str,
relationship_id: &str,
relationship_type: &str,
visibility: &str,
display: Option<Value>,
expires_at: Option<&str>,
) -> Value
Constructs a JSON payload for a relationship upsert event. Populates all required fields including the spec version and issued_at timestamp. The returned Value is ready to be passed to append_signed_event.
make_revoke_payload
pub fn make_revoke_payload(
event_id: &str,
issuer_did: &str,
subject: &str,
relationship_id: &str,
reason: Option<&str>,
) -> Value
Constructs a JSON payload for a relationship revocation event. Sets the event type, references the target relationship_id, and optionally includes a revocation reason.
File Locking
The append_signed_event function uses OS-level file locking to ensure safe concurrent access. When multiple processes attempt to append events simultaneously, only one will hold the lock at a time. Others will block until the lock is released. This guarantees that sequence numbers are assigned correctly and the events file remains consistent without requiring an external database or coordination service.
Sequence Management
Sequence numbers start at 1 and increment by 1 for each event appended to the feed. The server reads the existing events file to determine the current highest sequence, then assigns the next value. This means the events file is the single source of truth for ordering, and no separate counter file is needed.
Duplicate Event ID Rejection
Each event must carry a unique event_id. Before appending, the server scans all existing events in the feed and rejects any new event whose event_id has already been used. This prevents accidental double-publishing of the same event.