Skip to content

feat(D1): trust bootstrapping — seed Beta(α,β) from prior deployment on agent first-registration #65

@mdproctor

Description

@mdproctor

Context

When an agent joins a new CaseHub deployment for the first time, they start at Beta(1,1) = 0.5 (uniform prior — neither trusted nor distrusted). If the agent has an established track record in another deployment, that prior is discarded. Trust bootstrapping seeds the new deployment's score from the imported prior.

Part of: #52 (Group D epic)
Depends on: C2 (#64) — TrustImportService must exist

What to implement

Bootstrap trigger

When ActorTrustScore is first created for an actor (no existing record), call TrustBootstrapService before writing Beta(1,1):

@ApplicationScoped
public class TrustBootstrapService {

    @Inject TrustImportService importService;
    @Inject TrustBootstrapConfig config;

    /**
     * Called when an actor is seen for the first time in this deployment.
     * Attempts to seed their trust score from external sources.
     * Returns the seeded ActorTrustScore, or empty if no prior data found.
     */
    public Optional<ActorTrustScore> bootstrap(String actorId) {
        if (!config.enabled()) return Optional.empty();

        return fetchPriorTrust(actorId)  // calls configured bootstrap source
            .map(payload -> {
                importService.importTrust(payload, MergeStrategy.SEED_ONLY);
                return trustScoreRepository.findByActorId(actorId).orElse(null);
            });
    }
}

Bootstrap source SPI

public interface TrustBootstrapSource {
    /** Fetch prior trust data for an actor from an external source. */
    Optional<TrustExportPayload> fetchPriorTrust(String actorId);
}

@DefaultBean
@ApplicationScoped
public class NoOpTrustBootstrapSource implements TrustBootstrapSource {
    @Override
    public Optional<TrustExportPayload> fetchPriorTrust(String actorId) {
        return Optional.empty(); // no bootstrapping by default
    }
}

Configuration

casehub.ledger.trust.bootstrap.enabled=false     # opt-in
casehub.ledger.trust.bootstrap.source-url=       # URL of deployment to query (if using HTTP source)
casehub.ledger.trust.bootstrap.api-key=          # auth for remote trust export endpoint

Built-in HTTP source

@Alternative
@Priority(1)
@ApplicationScoped
public class HttpTrustBootstrapSource implements TrustBootstrapSource {
    // Calls GET /ledger/trust/export/actor/{actorId} on configured source-url
    // Returns the payload or empty if 404
}

Tests

  • First-time actor + bootstrap enabled + source returns data → score seeded
  • First-time actor + bootstrap enabled + source returns empty → Beta(1,1) used
  • First-time actor + bootstrap disabled → Beta(1,1) always used
  • Existing actor → bootstrap NOT called (already has a score)
  • HTTP source correctly calls and parses the remote export endpoint

Motivating use case

A client organisation deploys CaseHub. They know which agents have strong security-review track records from the vendor's reference deployment. With bootstrap enabled and the vendor's deployment as source, agents join the client's system with appropriate trust priors. First-week routing is as effective as sixth-month routing would be without bootstrapping.

Acceptance criteria

  • TrustBootstrapService called on actor first-registration in TrustScoreJob
  • TrustBootstrapSource SPI with NoOpTrustBootstrapSource as @DefaultBean
  • HttpTrustBootstrapSource as built-in @Alternative
  • Config keys: enabled, source-url, api-key
  • Bootstrapping only fires once per actor per deployment (not on every TrustScoreJob run)
  • Tests covering all scenarios

Refs #52
Depends on: #64

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions