Repository navigation
External Trust Integration
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
This document explains how Sigvara integrates external trust through ERC-8004 reputation registries. It covers how linked agent feedback is retrieved from external sources, normalized into a common scale, and converted into Sigvara’s scoring framework. It also documents the scaling algorithm that maps heterogeneous external ratings (the recognized tags use scales of 0 to 100, 0 to 1 and 0 to 5) to Sigvara’s 25-point external factor within the 0 to 100 score, the trust weighting mechanism for external influence, configuration options, fallback behavior when external data is unavailable, caching strategies, and security considerations around trusting external data sources.
External trust integration spans three layers:
- Oracle orchestration: reads linked agents, calls the external module, and composes the full score.
- External registry client: reads ERC-8004 feedback, verifies ownership, normalizes tags, and returns a bounded factor.
- Scoring and on-chain storage: aggregates factors and stores the finalized score with maturity and challenge windows.
graph TB
OR["Oracle index.js<br/>epoch loop"] --> EXT["external.js<br/>ERC-8004 reader"]
OR --> SC["scoring.js<br/>factor aggregation"]
OR --> CH["chain.js<br/>counterparty standing"]
SC --> REP["SigvaraReputation.sol<br/>store + maturity"]
EXT --> EREP["ERC-8004 Reputation Registry"]
EXT --> EID["ERC-8004 Identity Registry"]
Diagram sources
Section sources
- ERC-8004 external reader (
external.js): fetches signed feedback, verifies ownership and normalizes recognized tags;reviewers.jsdecides which reviewers count and returns the capped external factor. - Oracle epoch controller (
index.js, withlink-scan.jsandlink-claims.jsfor links made on chain): links Sigvara agents to ERC-8004 identities, retrieves external scores, and feeds them into the scoring function. - Scoring aggregator (
scoring.js): combines fee, success, tenure, external trust, community, and propagation factors into a total out of 100. - Counterparty standing helper (
chain.js): computes inherited trust using each counterparty’s external standing capped by their matured total. - On-chain reputation store (
SigvaraReputation.sol): validates proposed factors, enforces caps, manages proposals, challenges, finalization, and maturity.
Section sources
- external.js:1-39
- index.js:1349-1383
- scoring.js:130-155
- chain.js:465-474
- SigvaraReputation.sol:369-448
The external trust path begins with a link between a Sigvara agent and an ERC-8004 identity its operator owns. The agent makes it on chain, with no credential, by setting that identity's sigvara metadata key to its didHash (integration.md:167-196). An oracle operator can also make one with POST /link, which needs a write credential (scope link) and is refused with 403 when the identity is not owned by the agent’s operator. When both exist, the link made on chain applies (index.js:546-557). During each oracle epoch, the oracle reads the linked agent’s feedback from the ERC-8004 Reputation Registry, normalizes recognized rating dimensions, and converts them into a single external factor. That factor contributes up to 25 points toward the 100-point total. The contract stores and serves the score; computation remains off-chain.
sequenceDiagram
participant Operator as "Operator"
participant Oracle as "Oracle index.js"
participant External as "external.js"
participant ID as "ERC-8004 Identity"
participant Rep as "ERC-8004 Reputation"
participant Scorer as "scoring.js"
participant Store as "SigvaraReputation.sol"
Operator->>ID : setMetadata(agentId, 'sigvara', didHash)
Oracle->>External : link scan (link-scan.js)
External->>ID : MetadataSet logs, getMetadata(agentId, 'sigvara')
Oracle->>External : externalScoreFor(agentId, operator)
External->>ID : ownerOf(agentId)
ID-->>External : owner address
External->>Rep : getClients / getLastIndex / readFeedback
Rep-->>External : raw feedback rows
External-->>Oracle : normalized externalScore (0-25)
Oracle->>Scorer : computeScore(externalScore + other factors)
Scorer-->>Oracle : total score (0-100)
Oracle->>Store : proposeReputation(data, evidenceRoot)
Store-->>Oracle : pending proposal
Diagram sources
- The external module initializes only when all three environment variables are set: RPC URL, identity registry address, and reputation registry address. If any are missing, the module is inert and every external score becomes zero.
- For each linked agent, ownership is verified by checking that the ERC-8004 NFT owner matches the Sigvara operator wallet. Any error or mismatch yields zero. Scoring calls
ownerOf(agentId)on the ERC-8004 Identity Registry, and with links made on chain alsogetMetadata(agentId, "sigvara")and the registry'sMetadataSetlogs (external.js:205-235); the Reputation Registry is read withgetClients,getLastIndexandreadFeedback. - Feedback is fetched per client via
getClients, thengetLastIndex, thenreadFeedback. Revoked feedback is skipped, and index gaps are tolerated. - Each feedback row contains a value, decimals, and tag(s). The value is scaled by its decimals, and the tag is lowercased before normalization.
flowchart TD
Start(["externalScoreFor"]) --> CheckEnabled{"EXTERNAL_* configured?"}
CheckEnabled --> |No| ReturnZero["Return 0"]
CheckEnabled --> |Yes| VerifyOwner["Verify ERC-8004 NFT owner == operator"]
VerifyOwner --> OwnerOK{"Owner matches?"}
OwnerOK --> |No| ReturnZero
OwnerOK --> |Yes| ReadClients["Read clients for agentId"]
ReadClients --> LoopClients{"For each client"}
LoopClients --> GetIndex["Get last feedback index"]
GetIndex --> LoopIndices{"For i = 1..last"}
LoopIndices --> ReadFB["Read feedback(row)"]
ReadFB --> Revoked{"isRevoked?"}
Revoked --> |Yes| NextIndex["Skip"]
Revoked --> |No| NormalizeRow["Normalize value by decimals + tag"]
NormalizeRow --> Accumulate["Accumulate recognized rows"]
Accumulate --> NextIndex
NextIndex --> LoopIndices
LoopIndices --> ComputeMean["Keep qualifying reviewers (reviewers.js), weighted mean over clusters"]
ComputeMean --> ScaleFactor["Scale to at most 25, in full with five independent reviewers"]
ScaleFactor --> End(["Return externalScore"])
Diagram sources
Section sources
The owner of an ERC-8004 agent links it to a Sigvara agent by calling setMetadata(agentId, "sigvara", didHash) on the Identity Registry, with the 32-byte didHash as the value. Only that owner, or an address it approved, can set the key, and every operator reads the same logs, so the primary and the checker find the same links (link-claims.js:3-16).
-
Read only on the oracle's own chain. An oracle reads these links when
EXTERNAL_LINK_FROM_BLOCKis set and its ERC-8004 registry is on the chain it scores, as on Arc testnet. ElsewherePOST /linkis the only way (index.js:515-532). -
Made by the agent's operator. Each epoch scans the registry's
MetadataSetlogs for the key since the last scan, and keeps a claim only if the didHash is a registered Sigvara agent and, as of the log's block, the 8004 agent names it and is owned by that agent's operator, as it was in the block before. The second test stops a contract from minting an 8004 agent, naming someone else's didHash and handing the NFT to that agent's operator in one transaction (link-scan.js:26-56, index.js:559-571). - Applied from the next snapshot. The link that applies is the newest claim made at or before the day's snapshot block that still holds there: the key still returns the didHash, and the operator still owns the NFT. So a link made today applies from the next UTC day, and clearing the key or transferring the NFT undoes it from the next snapshot (link-scan.js:148-169, reputation-model.md:488-505).
- A scan that falls behind costs scoring, on purpose. An epoch whose scan has not reached the snapshot block skips the agents named by the logs it has not checked, because it could be missing a link the other operator holds. One that cannot list those logs, or read the registry's chain, scores nothing and counts as failed (index.js:1118-1183, index.js:1343-1347).
Section sources
- link-claims.js:24-66
- link-scan.js:26-56
- link-scan.js:148-169
- index.js:515-532
- index.js:1118-1183
- integration.md:167-196
- operations-runbook.md:336-355
- Thirteen tags are recognized and mapped to a rating from 0 to 1 (external.js:41-67):
starred,successrate,uptime,quality,trustscore,reliability,accuracyandcreditare divided by 100,reachableandwin-rateare used as is, andrating,e2e-testandstarsare divided by 5, each clamped to 0 to 1.starred,successrate,uptimeandreachableare the examples the ERC-8004 spec and its guide give (external.js:46-51); the guide'sownerVerified,responseTime,blocktimeFreshness,revenuesandtradingYieldare ignored (reputation-model.md:506-513). - Unrecognized tags are excluded rather than guessed, preserving meaningfulness. A tag is matched against the normalizer table by its own key only, because the tag is text chosen by whoever posts the feedback and a plain object also answers to
constructorand__proto__. - The registry takes feedback from any address, so until 3 November 2026 one fresh wallet posting
quality=100could carry a linked agent to 25. Feedback now counts only from a reviewer that paid the agent in a payment the oracle verified, is an Active, bonded Sigvara agent registered for 30 days with a matured score of at least 40, and was not funded by the agent's side (reviewers.js:135-178). - A reviewer is matched to its Sigvara agent by the address it posts from, so it must post from its Sigvara agent address. One that follows the ERC-8004 guide and posts from its
agentWalletshould make that wallet its Sigvara agent address, or its feedback is not matched to it (reputation-model.md:514-518). - One rating per reviewer, the mean of its recognized ratings. Reviewers sharing an operator, or a funder within two hops of them or their operator, are one cluster; a funder is the largest transfer in the first block where the wallet held 1 USDC or sent a transaction, and the zero address and
EXTERNAL_PUBLIC_FUNDERSend a trace. - The factor is the recency-weighted mean over clusters, each reviewer weighted by
0.5^(days since it last paid / 90), timesmin(1, total weight / 5), rounded and scaled to a maximum of 25 points, the external cap kept inoracle/score-caps.js(reviewers.js:210-249). One independent reviewer who paid recently is worth at most 5. - Everything is read as of the start of the UTC day (the feedback too when the ERC-8004 registry is on the oracle's own chain, as on Arc testnet; otherwise at its latest block), so a checker re-running the filter for a proposal reads what its primary read (index.js:462-576). A payment or review made today counts from tomorrow. A reviewer read the node cannot answer skips the agent for the epoch.
- In the overall scoring model, this external factor contributes up to 25 of the 100 total points. Other factors contribute fee activity (up to 20), success rate (up to 15), tenure (up to 30), community (up to 5), and propagation (up to 5).
flowchart TD
Rows["Raw feedback rows"] --> Filter["Filter recognized tags"]
Filter --> MapNorm["Map each value to 0-1 via TAG_NORMALIZERS"]
MapNorm --> Mean["Per reviewer mean; keep qualifying reviewers; recency-weighted mean over clusters"]
Mean --> Clamp["Scale by min(1, weight / 5), at most 25"]
Clamp --> Factor["externalScore factor (0-25)"]
Factor --> Total["Sum with other factors to get total (0-100)"]
Diagram sources
Section sources
- external.js:41-89
- scoring.js:130-155
- reputation-model.md:143-193
- reviewers.js:3-51
- reviewers.js:210-249
- External trust influences two parts of the score:
- Direct external factor: normalized ERC-8004 feedback contributes up to 25 points.
- Propagation factor: counterparties’ external standing raises the value of their evidence and contributes up to 5 points.
- Counterparty standing is computed as the minimum of the counterparty’s external score and their matured total. This prevents laundering a farmed total into another agent’s trust and ensures only external standing propagates.
- An unregistered or slashed counterparty has none. A counterparty the node could not answer for is not read as having none: the read is retried, and if it still fails the agent is skipped for that epoch, because scoring on a missing standing would lower the proposal for the wrong reason.
flowchart TD
Payer["Counterparty"] --> ExtStanding["Counterparty.externalScore"]
Payer --> MaturedTotal["Counterparty.maturedTotal"]
ExtStanding --> Cap["min(externalScore, maturedTotal)"]
MaturedTotal --> Cap
Cap --> EvidenceCap["Raise per-payer evidence cap"]
Cap --> Propagation["Add up to 5 propagation points"]
Diagram sources
Section sources
- Environment variables:
-
EXTERNAL_RPC: RPC endpoint for the ERC-8004 chain. -
EXTERNAL_IDENTITY_ADDRESS: ERC-8004 Identity Registry address. -
EXTERNAL_REPUTATION_ADDRESS: ERC-8004 Reputation Registry address. -
EXTERNAL_LINK_FROM_BLOCK: the block to read links made on chain from (index.js:117-121). Unset, links come only fromPOST /link. Both operators must use the same block, and while it is set a registry whose chain cannot be read stops all scoring.
-
- When all three are set, the external module is enabled. Otherwise, it is disabled and external scores default to zero.
- Chain health reporting:
-
configured()indicates whether the three values are present. -
refreshChainId()resolves and caches the actual chain ID. -
chainState()reports one of: disabled, configured, or unreachable.
-
classDiagram
class ExternalModule {
+init(cfg)
+configured() bool
+refreshChainId() number|null
+chainState() object
+externalScoreFor(agentId, expectedOwner) number
+verifyOwnership(agentId, expectedOwner) bool
+computeExternalScore(rows) number
}
class Config {
+externalRpc string
+externalIdentity string
+externalReputation string
}
ExternalModule --> Config : "reads"
Diagram sources
Section sources
- Disabled feed: if
EXTERNAL_*is unset,externalScoreForreturns zero without throwing. - Unreachable RPC: chain state reports “unreachable,” and individual reads fail safely, returning zero.
- Epoch resilience: failures in external reads do not abort the epoch; they yield zero for that factor. Links made on chain are the exception: with
EXTERNAL_LINK_FROM_BLOCKset, an epoch that cannot read the registry's chain, or list the link logs its scan has not checked, scores nothing, and a link check the node cannot answer skips the agent (index.js:1157-1183, index.js:546-557). - These fallbacks are for the ERC-8004 feed. On Sigvara's own chain a read the node could not get an answer to (throttled, timed out or dropped) is retried and, if it still fails, skips the agent for that epoch instead of yielding zero; a read that reverts counts as no standing.
flowchart TD
Enabled{"EXTERNAL_* configured?"}
Enabled --> |No| Zero["externalScore = 0"]
Enabled --> |Yes| Reachable{"RPC reachable?"}
Reachable --> |No| Zero
Reachable --> |Yes| Ownership{"NFT owner == operator?"}
Ownership --> |No| Zero
Ownership --> |Yes| Fetch["Fetch + normalize feedback"]
Fetch --> Result["externalScore (0-25)"]
Diagram sources
Section sources
- Chain ID caching:
refreshChainId()resolves and caches the chain ID once per initialization, avoiding repeated network calls. - Per-epoch payer score cache: the oracle caches counterparty standing across agents within an epoch to avoid redundant chain reads.
- Concurrency batching: ethers batches independent JSON-RPC calls issued in the same tick, reducing round trips during phase-one reads.
- Timeouts: external reads use a timeout wrapper to prevent long stalls from blocking the epoch.
flowchart TD
Init["external.init()"] --> CacheCID["Cache chainId"]
EpochStart["Epoch start"] --> ClearPayerCache["Clear payerScoreCache"]
PayerLookup["Resolve counterparty standings"] --> BatchCalls["Batch Promise.all calls"]
BatchCalls --> StoreCache["Store in payerScoreCache"]
ExternalReads["External feedback reads"] --> Timeout["withTimeout(promise)"]
Diagram sources
Section sources
- Ownership verification: before trusting ERC-8004 feedback, the module checks that the ERC-8004 NFT owner matches the Sigvara operator. This prevents claiming another agent’s reputation.
- Opt-in design: external integration is disabled unless explicitly configured, ensuring no accidental reliance on untrusted data.
- Avoiding double-counted signals: CounterAudit publishes under its own
counteraudittag, which the normalizer does not recognise, so the same signal is not counted twice. - Sigvara's own posts never feed back: its publisher posts under
sigvara/score, which the normalizer does not recognise either, and a test fails if any recognised tag starts withsigvara(publisher-policy.test.js:17-22). The publisher is also not a Sigvara agent, and must never be registered as one, soreviewers.jswould not count it either (0008-sigvara-as-erc8004-signal-provider.md:68-83). - Contract-side validation: proposed factors are validated against maximum caps; invalid proposals revert.
- Maturity and challenge window: scores become spendable over time and can be challenged before finalization, mitigating farm-and-cash-out risks.
flowchart TD
Input["External feedback"] --> Verify["Verify NFT ownership"]
Verify --> TagCheck{"Tag recognized?"}
TagCheck --> |No| Exclude["Exclude from normalization"]
TagCheck --> |Yes| Normalize["Normalize to 0-1"]
Normalize --> Aggregate["Filter reviewers, weighted mean → 0-25"]
Aggregate --> Validate["Contract validates caps"]
Validate --> Challenge["Challenge window"]
Challenge --> Finalize["Finalize + maturity"]
Diagram sources
- external.js:193-251
- external.js:41-89
- architecture.md:137-147
- SigvaraReputation.sol:369-448
- SigvaraReputation.sol:696-752
Section sources
- external.js:193-251
- external.js:41-89
- architecture.md:137-147
- SigvaraReputation.sol:369-448
- SigvaraReputation.sol:696-752
The other direction. ERC-8004's guide expects catalogs to filter feedback by trusted signal providers, so Sigvara posts its scores as ERC-8004 feedback from one address it names as its own, and any catalog that trusts that address can show them (0008-sigvara-as-erc8004-signal-provider.md:6-31).
-
Who posts. Sigvara is ERC-8004 agent 897764 on Arc testnet (agent-registration.json:1-24). The publisher posts from the address set as that registration's
agentWallet, which the deployer sets with a signature from the publisher's key, inside the registry's five-minute window (agent-wallet.js:1-21, SetAgentWallet.s.sol:13-32). One publisher runs, beside the primary and never on the checker, so each score appears once (publisher.js:3-20). -
What it posts. For each agent linked on chain, the spendable score (
getTotalScore), 0 to 100, taggedsigvara/score, with adata:feedback file that holds the earned score and the block and time it was read at. It posts after a finalized score or a slash, and, for an agent with a score event sincePUBLISH_FROM_BLOCK, in the run that finds its first link (publisher.js:107-118). A link that moves waits for the agent's next score event or the daily refresh, which reads every scored agent again because maturity changes without an event. It posts at most once a day per agent, except a zero after a slash, which goes out at once (publisher-policy.js:18-57, publisher-policy.js:84-90, publisher.js:71-127). -
Revoke-and-post.
getSummaryaverages every feedback not revoked, so before posting it revokes its own livesigvara/scorefeedback on that 8004 agent, among its last eight, and keeps the history. An agent that unlinks has its score revoked where it was posted, and after a slash that 8004 agent is set to 0 whatever the link says by then (publisher-policy.js:59-82, publisher.js:209-226, operations-runbook.md:401-518). -
Gates. In shadow mode, the default, it reads everything and sends nothing. In live mode it sends only while the registration's
agentWalletis the publisher, the remote signer signs as the publisher, the balance is at least a floor, and none of its transactions is still pending (publisher-policy.js:92-110). In either mode a run whose link scan has not reached the block it reads at posts nothing (publisher.js:152-157). -
The key. The publisher holds no key. It signs through a policy signer on another host, which signs only
giveFeedbackwith Sigvara's tags and adata:file,revokeFeedback, and theAgentWalletSetmessage for agent 897764. Each transaction must be at the publisher's next nonce, under gas, fee and hourly caps, and each request carries an HMAC over its time and body (signer.js:62-127, signer.js:166-168, signer-auth.js:1-46). On testnet the key is an encrypted keystore; mainnet needs a KMS or HSM behind it (signer.js:22-23). -
Status. Posting for every agent was to start after the registration, the
agentWalletcheck and one end-to-end cycle on testnet, a revoke and a post on one agent (0008-sigvara-as-erc8004-signal-provider.md:156-164). On 3 November 2026 the simulation's solo agent linked itself as ERC-8004 agent 897766 (0xd0a90956...), and the publisher, live then for that agent only, posted its spendable score of 3 there (0xcb1fe003...). That was the post half of the cycle. The allow list was emptied early on 4 November, and the publisher has posted for every agent linked on chain since. The other half ran later that day: when the agent's score changed, the publisher revoked its first feedback (0xea811f75...) and posted the new score (0x7039099e...), andgetSummaryreturned a count of 1 and a value of 4 (operations-runbook.md:520-552). Mainnet stays behind the audit and the launch gates.
Section sources
- 0008-sigvara-as-erc8004-signal-provider.md:6-31
- 0008-sigvara-as-erc8004-signal-provider.md:68-83
- 0008-sigvara-as-erc8004-signal-provider.md:156-164
- 0008-sigvara-as-erc8004-signal-provider.md:189-199
- publisher.js:3-20
- publisher-policy.js:59-113
- signer.js:62-127
- operations-runbook.md:401-518
External trust depends on:
- Oracle orchestration: coordinates linked agents, external reads, and scoring.
- ERC-8004 registries: provide canonical identity and raw feedback.
- Scoring logic: aggregates factors and clamps totals.
- Counterparty standing: uses external standing to weight evidence and propagate trust.
- On-chain store: enforces caps, manages proposals, and exposes matured scores.
graph LR
Index["index.js"] --> External["external.js"]
Index --> Scoring["scoring.js"]
Index --> Chain["chain.js"]
Scoring --> Reputation["SigvaraReputation.sol"]
External --> ERC8004ID["ERC-8004 Identity"]
External --> ERC8004Rep["ERC-8004 Reputation"]
Diagram sources
Section sources
- Batching: independent chain reads are batched to reduce HTTP overhead.
- Chunking: large scans are split into chunks to avoid RPC limits and backpressure.
- Caching: chain ID and per-epoch payer scores are cached to minimize repeated calls.
- Timeouts: external reads are wrapped with timeouts to prevent epoch stalls.
- Concurrency: phase-one reads are concurrent but chunked to balance throughput and provider limits.
- External feed disabled: verify all three environment variables are set. If any are missing, external scores will be zero.
- Unreachable RPC: check
chainState()for “unreachable” status and inspect the error message. Ensure the RPC endpoint is valid and accessible. - Ownership mismatch: ensure the ERC-8004 NFT owner matches the Sigvara operator address. A mismatch results in zero external score.
- Link made on chain not applied yet: it applies from the next UTC day's snapshot, and only if, when the key was set, the Sigvara agent was already registered and its operator had owned the 8004 agent since a block before. Set the key in a transaction of its own after the NFT is minted, not in the
registercall (integration.md:167-196). - Scoring stopped with
the ERC-8004 registry's chain could not be readorits logs could not be listed: withEXTERNAL_LINK_FROM_BLOCKset, an unreadable registry stops scoring on purpose. Followdocs/operations-runbook.md, section 3, "ERC-8004 links made on chain" (operations-runbook.md:336-355). - No recognized tags: if feedback uses unrecognized tags, the normalizer excludes them, resulting in zero external score. Add recognized tags or extend the normalizer deliberately.
- No qualifying reviewers: feedback from wallets that never paid the agent, or that are not bonded Sigvara agents registered for 30 days with a score of at least 40, is not counted, and the factor is 0 on an operator that verifies no payments (
PAYMENT_VERIFICATIONand the pull scanner both off). The epoch log names the reasons, for exampleexternal: 0/25 from 0 reviewer(s) in 0 cluster(s); not counted: unpaid 3. - Epoch failures: apart from the link reads above, external read errors should not abort the epoch. Inspect logs for warnings about external read timeouts or RPC failures.
Section sources
Sigvara’s external trust integration leverages ERC-8004 to bring cross-protocol reputation into its scoring model. The system retrieves signed feedback, verifies ownership, normalizes recognized rating dimensions, and scales them into a bounded external factor. That factor contributes up to 25 points to the 100-point total and also influences counterparty evidence and propagation. The design is opt-in, resilient to failures, and secured by ownership checks, contract-side validation, and maturity/challenge mechanisms. Operators can configure external providers, monitor feed health, and rely on caching and batching for performance.
- Agent Registration and Lifecycle
- Contract Overview and Architecture
- Economic Security Model and Incentives
- Evidence Verification and Merkle Proofs
- Key Management and Rotation
- Maturity Mechanism and Score Release
- Proposal Workflow and Challenge System
- Score Storage and Data Model
- SigvaraIdentity Contract
- SigvaraOracleBond Contract
- SigvaraReputation Contract
- SigvaraStaking Contract
- Slashing Lifecycle and Dispute Resolution
- Stake Management Functions
- Status Management and Control
- Token and Fee Contracts
- Unbonding Period and Withdrawal Security
- Anti-Manipulation and Security Measures
- Community Flag Processing
- Evidence Sources and Verification
- External Trust Integration
- Merkle Proof System
- Oracle Score Computation
- Payment-Backed Attestations
- Scoring Model and Formulas
- Agent Creation and Key Management
- Agent Operations
- Agent Registration Workflow
- Challenge-Response Authentication
- Gate Access Control
- Integration Patterns and Examples
- SDK Overview and Setup
- Verifier Functions