Class ReplicatedSpace

java.lang.Object
ai.badmonkey.agentspaces.space.replicated.ReplicatedSpace
All Implemented Interfaces:
Space, AutoCloseable

public final class ReplicatedSpace extends Object implements Space, AutoCloseable
The replicated AgentSpace (spec §7): the same Space interface as LocalSpace, backed by the delta-CRDT replica and the group's gossip bus. Writes, completions, and take claims ride the rumor channel as deltas; anti-entropy reconciles anything rumors missed; and every replica evaluates the same deterministic rules, so replicas that have seen the same updates agree.

Exclusive take runs the LEASE_RACE strategy (spec §7.4): a claim is a TakeClaim lattice value published as a delta; after the settle window the deterministic merge decides the winner identically on every replica. At most one complete survives per entry (the CRDT's monotone completed flag), and transient duplicate work during partitions is the documented trade-off, so tasks should be idempotent.

Entry records are signed over their immutable identity (id, space, type, payload, issuer, issue stamp, tags), and receivers verify the signature and the writer's self-certifying identity before merging a delta.

Lifecycle (spec §7.5): a space built with ReplicatedSpace.Builder.advertise(DiscoveryPublisher) publishes its signed SpaceAdvertisement on creation and on refreshAdvertisement(); ReplicatedSpace.Builder.admission(SpaceAdmission) restricts who may write, take, and complete (under CREDENTIAL the issuer's node hands out leased SpaceCredential entries with grant(AgentId, Set, Duration) and withdraws them with revoke(AgentId)); and ReplicatedSpace.Builder.founderLease or markReadOnly() turns the space read-only. Lease lapses surface as EXPIRED and REAPPEARED events from the sweep that the anti-entropy tick (or sweepNow()) runs, and the same sweep collects tombstones twice the maximum lease after their lease lapsed (spec §7.3).

  • Method Details

    • builder

      public static ReplicatedSpace.Builder builder(GroupRuntime runtime, String name, PeerIdentity identity, String agentName)
      Starts building a replicated space attached to a group.
      Parameters:
      runtime - the group runtime
      name - the space name within the group
      identity - the local peer identity (signs entries)
      agentName - the local agent name writes are attributed to
      Returns:
      the builder
    • name

      public String name()
      Description copied from interface: Space
      Returns the space's name within its group.
      Specified by:
      name in interface Space
    • writer

      public Optional<AgentId> writer()
      Description copied from interface: Space
      The agent this handle attributes its writes to, when the implementation knows it. Every entry written through this handle is signed and reported by readAllIssued and SpaceEvent as coming from this agent, whatever the entry itself declares.

      Exposed so that a component holding both a handle and an identity can check they agree before it writes something only the matching identity could have written — a ballot names its voter, and a ballot whose declared voter is not this agent is dropped as forged at every replica, including the writer's own (QA4 A4-4). Empty when the implementation does not track a single writer; a caller that cannot tell must not guess.

      Specified by:
      writer in interface Space
      Returns:
      the writing agent, or empty when unknown
    • as

      public Space as(AgentIdentity actor)
      A per-agent view of this replica (SPEC §4.2, QA4 A4-7 phase 3): the same space — one replica, one gossip registration, one clock per node — seen through another agent's identity. Records the view writes are issued and signed by actor (attested when it is a subordinate identity), take claims and completions through it name actor as the holder, and admission is judged for actor, so two views of one replica can be admitted differently under ALLOWLIST or CREDENTIAL. Reads and subscriptions are the replica's own. The view has no resources of its own: closing this space ends every view, and views do not close.
      Parameters:
      actor - the agent the view acts as; must belong to this peer
      Returns:
      the view
      Throws:
      IllegalArgumentException - when the actor is another peer's agent
    • id

      public SpaceId id()
      Description copied from interface: Space
      Returns the space's identifier.
      Specified by:
      id in interface Space
    • strategy

      public ConflictStrategyType strategy()
      Returns the space's declared conflict strategy.
    • bidFunction

      public void bidFunction(ToDoubleFunction<Object> bidFunction)
      Replaces the AUCTION bid function (for binder-driven wiring).
      Parameters:
      bidFunction - the cost function
    • refreshAdvertisement

      public Optional<SignedAdvertisement<SpaceAdvertisement>> refreshAdvertisement()
      Re-publishes the space's signed advertisement with a fresh issue instant and the schema hints registered so far (spec §7.5). The founders' refresh loop calls this within the advertisement TTL. A no-op returning empty when the space was built without ReplicatedSpace.Builder.advertise(DiscoveryPublisher) or has become read-only: letting the advertisement lapse is how founders release a space.
      Returns:
      the advertisement published, when one was
    • advertisement

      Returns the most recently published advertisement, when the space advertises.
    • admission

      public SpaceAdvertisement.Admission admission()
      Returns the space's advertised admission rule (spec §7.5).
    • admissionRule

      public SpaceAdmission admissionRule()
      Returns the admission rule object the space asks (spec §7.5, TECH-SPEC §7.10).
    • allowedAgents

      public Set<AgentId> allowedAgents()
      Returns the agents admitted under ALLOWLIST; empty under every other rule.
    • credentialIndex

      public Optional<CredentialIndex> credentialIndex()
      Returns the credential index this replica maintains under CREDENTIAL admission.
    • grant

      public EntryHandle grant(AgentId agent, Set<SpaceAdmission.Scope> scopes, Duration validity)
      Issues a space credential (spec §7.5): writes a SpaceCredential entry admitting agent for scopes, with a write lease of validity that is the credential's expiry. Because it is an ordinary signed entry it replicates like any write, and a replica admits the agent once the entry is present there. The returned handle renews or cancels the credential like any entry; a credential nobody renews lapses on its own. Only the configured credential issuer's node may grant.
      Parameters:
      agent - the agent to admit
      scopes - the scopes granted
      validity - how long the credential lives unless renewed
      Returns:
      the credential entry's handle
      Throws:
      SpaceAdmissionException - when this space does not admit by credential or this node is not its issuer
    • revoke

      public void revoke(AgentId agent)
      Withdraws every live credential this replica holds for an agent (spec §7.5) by cancelling the credential entries. Cancellation replicates like any removal, so the revocation is fleet-wide within one gossip round. Only the configured credential issuer's node may revoke.
      Parameters:
      agent - the agent whose credentials are withdrawn
      Throws:
      SpaceAdmissionException - when this space does not admit by credential or this node is not its issuer
    • founderLeaseExpired

      public boolean founderLeaseExpired()
      Whether the founders' lease on the space has lapsed on this replica's clock (spec §7.5). Always false when no founder lease was set.
      Returns:
      true once the deadline has passed
    • readOnly

      public boolean readOnly()
      Whether the space refuses writes and takes: founder lease lapsed or marked read-only.
    • markReadOnly

      public void markReadOnly()
      Makes the space read-only now (spec §7.5); reads keep working. Irreversible.
    • renewFounderLease

      public void renewFounderLease(Duration extension)
      Extends the founders' lease on the space from now.
      Parameters:
      extension - how much longer the founders hold the space
      Throws:
      SpaceReadOnlyException - when the space is already read-only
    • sweepNow

      public void sweepNow()
      Applies lease lapses now (spec §7.2, §7.3): fires EXPIRED for entries whose write lease lapsed and REAPPEARED for entries whose take claim lapsed without completion, once per transition, and collects tombstones older than twice the maximum lease. The anti-entropy tick runs the same sweep; call this to sweep without traffic.
    • maxLeaseMillis

      public long maxLeaseMillis()
      The maximum lease the tombstone collector reckons with right now, in milliseconds.
    • write

      public <T> EntryHandle write(T entry, Lease lease)
      Description copied from interface: Space
      Publishes an entry under a write lease. The lease is the entry's TTL: an unrenewed entry vanishes when the lease lapses (spec P2).
      Specified by:
      write in interface Space
      Type Parameters:
      T - the entry type
      Parameters:
      entry - the entry to publish
      lease - the write lease
      Returns:
      a handle for renewing or cancelling the entry
    • write

      public <T> EntryHandle write(T entry, Lease lease, Map<String,String> tags)
      Description copied from interface: Space
      Publishes an entry under a write lease, tagged for routing and sharding. Tags are free-form key-value pairs carried on the entry record and covered by the writer's signature; a replica configured with a tag shard stores only entries whose tags match its shard (spec §7.5).
      Specified by:
      write in interface Space
      Type Parameters:
      T - the entry type
      Parameters:
      entry - the entry to publish
      lease - the write lease
      tags - free-form tags, e.g. region=eu, tier=gold
      Returns:
      a handle for renewing or cancelling the entry
    • read

      public <T> Optional<T> read(Template<T> template, ConsistencyHint hint, Duration timeout)
      Reads with a consistency hint (spec §7.2): ConsistencyHint.FRESH performs exactly one anti-entropy pull toward one random group member before the local match; ConsistencyHint.LOCAL is read(Template, Duration).
      Type Parameters:
      T - the entry type
      Parameters:
      template - the template
      hint - how current the read must be
      timeout - how long to wait for a match
      Returns:
      the first match
    • readAll

      public <T> List<T> readAll(Template<T> template, ConsistencyHint hint, int limit)
      Reads all matches with a consistency hint (spec §7.2); see read(Template, ConsistencyHint, Duration).
      Type Parameters:
      T - the entry type
      Parameters:
      template - the template
      hint - how current the read must be
      limit - the maximum number of results
      Returns:
      the matches, up to limit
    • read

      public <T> Optional<T> read(Template<T> template)
      Description copied from interface: Space
      Non-destructive, non-blocking match against current local state.
      Specified by:
      read in interface Space
      Type Parameters:
      T - the entry type
      Parameters:
      template - the template to match
      Returns:
      a matching entry, if one exists now
    • read

      public <T> Optional<T> read(Template<T> template, Duration timeout)
      Description copied from interface: Space
      Non-destructive match, waiting up to the timeout for a matching entry.
      Specified by:
      read in interface Space
      Type Parameters:
      T - the entry type
      Parameters:
      template - the template to match
      timeout - how long to wait for a match
      Returns:
      a matching entry, or empty when the timeout elapses first
    • readAll

      public <T> List<T> readAll(Template<T> template, int limit)
      Description copied from interface: Space
      Non-destructive match returning up to limit entries present now.
      Specified by:
      readAll in interface Space
      Type Parameters:
      T - the entry type
      Parameters:
      template - the template to match
      limit - the maximum number of entries to return
      Returns:
      the matching entries, possibly empty
    • readAllIssued

      public <T> List<Space.Issued<T>> readAllIssued(Template<T> template, int limit)
      Description copied from interface: Space
      Non-destructive match returning up to limit entries present now, each paired with its authenticated writer.
      Specified by:
      readAllIssued in interface Space
      Type Parameters:
      T - the entry type
      Parameters:
      template - the template to match
      limit - the maximum number of entries to return
      Returns:
      the matching entries with their issuers, possibly empty
    • take

      public <T> Optional<TakenEntry<T>> take(Template<T> template, Lease takeLease, Duration timeout)
      Description copied from interface: Space
      Destructive, exclusive match under the space's conflict strategy (spec §7.4), waiting up to the timeout for a matching entry. The returned take holds a TAKE lease: if the taker dies or lets the lease lapse without completing, the entry reappears for other takers. That reappearance is the crash-recovery idiom of the model.
      Specified by:
      take in interface Space
      Type Parameters:
      T - the entry type
      Parameters:
      template - the template to match
      takeLease - the TAKE lease requested
      timeout - how long to wait for a match
      Returns:
      the taken entry, or empty when the timeout elapses or the strategy awards the entry elsewhere
    • readAllEntries

      public <T> List<Space.Entry<T>> readAllEntries(Template<T> template, int limit)
      Description copied from interface: Space
      Non-destructive match returning up to limit entries present now, each as an Space.Entry view over its record. Visibility is that of Space.readAll(Template, int): live, unclaimed, and decodable now.

      The default throws; both library spaces implement it.

      Specified by:
      readAllEntries in interface Space
      Type Parameters:
      T - the entry type
      Parameters:
      template - the template to match
      limit - the maximum number of entries to return
      Returns:
      the matching entries with their metadata, possibly empty
    • recordOf

      public Optional<EntryRecord> recordOf(EntryId entryId)
      The record this replica currently holds for an entry (issue #16 §9.3): present while the CRDT reports the entry present, whether it is available or claimed, and empty once it is completed, withdrawn, or unknown here. The ordered join uses it to read a ticket's tags for an entry id it learned from a committed claim, which a template read cannot see while claimed. The lease on the returned record is the one in force.
      Parameters:
      entryId - the entry
      Returns:
      the record, when the entry is present here
    • recordOf

      public Optional<EntryRecord> recordOf(EntryId entryId, boolean completedToo)
      recordOf(EntryId), optionally answering for a completed entry too, from the tombstone the CRDT keeps until the collection horizon (SPEC §7.3). The ordered join needs this: a member may learn of the first committed ticket claim for a key after that ticket's taker has already completed it, and must still read the ticket's key to know that a later ticket for the same key does not fire.
      Parameters:
      entryId - the entry
      completedToo - whether a completed entry's record is returned as well
      Returns:
      the record, when the replica holds one
    • schemaNameOf

      public String schemaNameOf(Class<?> type)
      The schema name this replica registers type under (issue #16 §10.2), registering it first when it is new, as a read or subscription would. A binder compares this with the name it advertises so a card and the space agree on a type's name.
      Parameters:
      type - the entry type
      Returns:
      the schema name
    • complete

      public void complete(TakenEntry<?> taken)
      Description copied from interface: Space
      Consumes a taken entry permanently.
      Specified by:
      complete in interface Space
      Parameters:
      taken - the take to complete
    • complete

      public <R> EntryHandle complete(TakenEntry<?> taken, R result, Lease resultLease)
      Description copied from interface: Space
      Consumes a taken entry permanently and atomically writes a result entry.
      Specified by:
      complete in interface Space
      Type Parameters:
      R - the result entry type
      Parameters:
      taken - the take to complete
      result - the result entry to write
      resultLease - the write lease for the result entry
      Returns:
      a handle for the written result entry
    • complete

      public <R> EntryHandle complete(TakenEntry<?> taken, R result, Lease resultLease, Map<String,String> tags)
      Description copied from interface: Space
      Consumes a taken entry permanently and atomically writes a tagged result entry (issue #16 §9.2): as Space.complete(TakenEntry, Object, Lease), with tags carried on the result's record exactly as Space.write(Object, Lease, Map) would carry them.

      The default throws; both library spaces and their per-agent views implement it.

      Specified by:
      complete in interface Space
      Type Parameters:
      R - the result entry type
      Parameters:
      taken - the take to complete
      result - the result entry to write
      resultLease - the write lease for the result entry
      tags - free-form tags for the result record
      Returns:
      a handle for the written result entry
    • notify

      public <T> Subscription notify(Template<T> template, SpaceListener<T> listener, Lease lease)
      Description copied from interface: Space
      Registers a leased subscription for events on entries matching the template. Delivery is at-least-once with entry-record deduplication; listeners receive a foundation for complex event processing over the entry stream.
      Specified by:
      notify in interface Space
      Type Parameters:
      T - the entry type
      Parameters:
      template - the template events must match
      listener - the listener to invoke
      lease - the subscription's lease
      Returns:
      the subscription; closing or letting it lapse stops delivery
    • close

      public void close()
      Specified by:
      close in interface AutoCloseable
    • currentClaim

      public Optional<TakeClaim> currentClaim(EntryId entryId)
      Returns the current take claim on an entry, when any replica claim is known here. Exposed for the ordered-log coordinator and for fleet consoles.
      Parameters:
      entryId - the entry
      Returns:
      the current claim
    • applyAuthorizedClaim

      public void applyAuthorizedClaim(EntryId entryId, TakeClaim claim, byte[] holderKey, byte[] signature)
      Installs a claim the ordered log committed, with the holder's own attestation (spec §7.4 ORDERED, QA4 A4-5). The coordinator verified signature over claim under holderKey before the command was ever committed; passing them through unchanged is what lets every replica later authenticate the holder's completion, because a completion is verified against the key the stored claim carries. The claim is never re-published as a rumor; the log is its replication channel, and the log's decision is authoritative for the claim's epoch.
      Parameters:
      entryId - the entry
      claim - the committed claim, exactly as the holder signed it
      holderKey - the holder's raw Ed25519 public key
      signature - the holder's signature over the claim's canonical bytes
      Throws:
      IllegalArgumentException - when the key does not belong to the claim's holder or the signature does not verify — the caller has proof that does not prove what it claims
    • applyAuthorizedClaim

      public void applyAuthorizedClaim(EntryId entryId, TakeClaim claim, byte[] holderKey, byte[] signature, AgentCertificate certificate)
      applyAuthorizedClaim(EntryId, TakeClaim, byte[], byte[]) for a claim the holder signed with a subordinate agent key: the certificate travels with the proof and the two-key rule verifies it (QA4 A4-7 phase 3).
      Parameters:
      entryId - the entry
      claim - the committed claim
      holderKey - the holder's peer key
      signature - the holder's signature, under its agent key when a certificate is given
      certificate - the peer's certificate for the agent key, or null for a peer-signed claim
    • verifiesAuthorizedClaim

      public boolean verifiesAuthorizedClaim(EntryId entryId, TakeClaim claim, byte[] holderKey, byte[] signature, AgentCertificate certificate)
      Whether a log-committed claim would be accepted by applyAuthorizedClaim(EntryId, TakeClaim, byte[], byte[], AgentCertificate), without installing it (issue #16): the ordered-log coordinator asks this for a committed claim whose generation this replica already holds through gossip, so that listeners on the committed order still hear of every authentic claim.
    • applyAuthorizedClaim

      public void applyAuthorizedClaim(EntryId entryId, TakeClaim claim)
      Installs a claim the ordered log committed without the holder's attestation: the stored proof is signed by this node, so it decides local arbitration but cannot authenticate the holder's completion at any other replica. Prefer applyAuthorizedClaim(EntryId, TakeClaim, byte[], byte[]) whenever the holder's signature is available, which for a log command it always is. Kept for callers that arbitrate locally and never complete.
      Parameters:
      entryId - the entry
      claim - the ordered claim
    • adoptClaim

      public <T> Optional<TakenEntry<T>> adoptClaim(Template<T> template, EntryId entryId)
      Adopts an entry whose current claim this agent already holds (placed through the ordered-log coordinator), returning a TakenEntry that complete(TakenEntry) accepts.
      Type Parameters:
      T - the entry type
      Parameters:
      template - the template naming the entry type
      entryId - the claimed entry
      Returns:
      the taken entry, or empty when this agent does not hold the claim
    • adoptClaim

      public <T> Optional<TakenEntry<T>> adoptClaim(Template<T> template, EntryId entryId, AgentIdentity holder)
      Adopts a log-decided claim as the given holder identity (v0.1.13), so a completion is signed by the agent that holds the claim, as an agent-attested claim's completion must be (SPEC §11a.4).
      Type Parameters:
      T - the entry type
      Parameters:
      template - the entry's template
      entryId - the claimed entry
      holder - the identity the claim names as its holder
      Returns:
      the taken entry, or empty when the claim is not this holder's
    • entryIdOf

      public Optional<EntryId> entryIdOf(Object value)
      Reverse-maps a value returned by read/readAll to its entry id among currently available entries. Exposed for take coordinators.
      Parameters:
      value - the entry value
      Returns:
      the entry id, when the value corresponds to an available entry
    • knownEntries

      public int knownEntries()
      Returns how many entries this replica knows about, tombstones included.
    • claimProof

      public Optional<SpaceWire.SignedClaim> claimProof(EntryId entryId)
      The stored proof of the current claim on an entry, when one is held: the claim, the holder's peer key, its signature, and — when the holder took through an agent key of its own — the peer's certificate for that key.
      Parameters:
      entryId - the entry
      Returns:
      the signed claim, or empty
    • signedState

      public Optional<SpaceWire.EntryStateDto> signedState(EntryId entryId)
      The most advanced actor-signed state this replica holds for an entry, as anti-entropy would forward it: the record, the issuer's peer key (and certificate, under a subordinate identity), the CRDT fields, and the state signature. Empty for an entry this replica does not know.
      Parameters:
      entryId - the entry
      Returns:
      the signed state
    • revocationView

      public RevocationView revocationView()
      The group's revocations as this space enforces them (SPEC §6.1, v0.1.13), for capabilities built over the space that must apply the same view.
      Returns:
      the revocation view
    • revocationViewOf

      public static RevocationView revocationViewOf(Space space)
      The revocation view behind a space handle: a replicated space's, or the one its per-agent view (as(AgentIdentity)) shares; NONE otherwise.
      Parameters:
      space - a space handle
      Returns:
      the view it enforces
    • keyRing

      public Optional<GroupKeyRing> keyRing()
      This space's content-key ring (SPEC §11a.3), when the space is encrypted.
      Returns:
      the ring