RODiT-Based IdentyClaw Passports — As-Built Architecture
DEV Community

RODiT-Based IdentyClaw Passports - As-Built Architecture

This document describes how the IdentyClaw Passport system actually works: the problem it addresses, the design decisions that still shape the running system, the trust model those decisions produce in code, the lifecycle a Passport follows today, and an assessment of where that architecture is strong and where it is exposed. It is not a line-by-line implementation audit. Hosts, ports, versions, and source paths are omitted because they change per environment and per release and they obscure the reasoning. Mechanisms, field names, and trust consequences are not omitted. Where a running behaviour diverges from the model the rest of the system still assumes, that divergence is stated in place rather than parked in an appendix. Design intent is cited only where it still governs what was built, or where a stated direction exists and has not been built yet. Scope. Eight identity components: the NEAR smart contract that acts as registry; the SDK that both issues and verifies; two signing services (Portal and Sanctum); three operator/purchase interfaces (root, server, client); and the IdentyClaw API that brokers client issuance and assists verification. A ninth, separate system is cited where it proves those mechanisms in public: Synthetics' Last Cradle, the live technology demonstrator (lastcradle-be / lastcradle-fe , public surfaces lastcradle.io and api.lastcradle.io). It is a federated peer that consumes Passports. 1. The problem being solved Machines and autonomous agents need to prove identity to parties they have no prior relationship with, over channels nobody controls, without a central authority mediating every interaction. Conventional answers fit poorly. X.509 assumes a CA hierarchy and a revocation infrastructure that must be online and trusted. API keys are bearer secrets with no verifiable provenance and no policy attached. OAuth assumes a common identity provider both sides accept. All three require the verifier to trust an intermediary at the moment of verification. The Passport design takes a different position: the credential itself is a publicly readable, independently verifiable object, and the subject owns it. Anyone can read it, nobody can alter it, and proving control of it requires no cooperation from its issuer. 2. Design decisions and their consequences Nine decisions do most of the architectural work. Each is stated as it is built, then the consequence that follows - including the costs, and including the places where the running system is softer than the decision sounds. 2.1 The credential is an on-chain asset owned by its subject A Passport is a token on a specific blockchain contract, owned by the subject's own account. It is not a record in a vendor's database, and not a signed blob the subject merely holds a copy of. After mint, metadata is never rewritten; the only mutable facts are owner and existence. Consequence. The issuer cannot silently alter or delete it, the subject can prove ownership without the issuer's participation, and any party can read it without asking permission. The cost is that the credential's existence, policy, and ownership history are public - which suits machine identity, and would not suit personal data. Transfer of the token to another account is also the only key-rotation mechanism (§4). The identity object is the token. The owning NEAR account signs, pays, and holds it; one account may hold many Passports or none, and accounts are cheap to create in bulk. Transfer replaces the owning account and keeps the identifier, so custody can change without renaming the entity. Proofs check the owner recorded now. Last Cradle seats a Passport. 2.2 The chain notarizes; verifiers enforce Policy - validity window, rate limits, permitted routes, network and geographic constraints - is stored on-chain. The contract validates that those fields are well-formed at issuance (dates, URLs, CIDR, JSON, identifier format, DN shape) and then treats their meaning as opaque. It also checks a fee attestation from its authorized-signer set and that the attached deposit matches the attested fee. Enforcement of the policy itself is the verifier's job, and only happens if that verifier actually runs the SDK middleware that consumes the claims. Consequence. Verification is a read, not a transaction: no gas, no chain write in the authentication path. This is what makes the system usable at API request rates. The cost is that policy is advisory - it binds only verifiers who choose to implement it, and only as correctly as they implement it. See §7.2. Issuance is a different gate: the contract requires a fee attestation from the authorized Portal/Sanctum keys. It does not, and need not, encode tiers. See §6. 2.3 Trust is walked from the verifier outward, never from the credential inward A presented Passport names its issuing lineage in serviceprovider_id . A verifier does not follow that pointer to discover keys. Instead it splits its own configured lineage, resolves each id= component on the registry it has pinned, derives the corresponding public key from that credential's owning account, and tests whether any of those keys signed the presented credential's policy hash. Consequence. A credential cannot nominate its own trust anchor. Forging a lineage claim achieves nothing unless one of the verifier's own issuers actually signed the policy. This inverts the usual certificate-chain vulnerability, where an attacker supplies both the leaf and the path to a root. It is the single strongest property in the design. It is also why a credential from a different registry is not rejected on policy grounds - it is unresolvable (§5.3, §8.1). 2.4 Issuance attenuates - on some paths, and not uniformly Each descent is supposed to issue only a subset of the authority the issuer holds. As built, attenuation is path-dependent. On the public client path, the IdentyClaw API is the broker: it prices the request, copies several policy fields from its own credential onto the child (home API URL, CIDR, JWT duration, not_before ), refuses routes the broker itself does not have, and refuses privileged operations. It does not uniformly refuse a broader validity window or a higher rate limit than it holds. The signing service then attests whatever the broker forwarded, after rewriting lineage. On the server path, Sanctum attests values the operator interface submitted. Membership is enforced because Sanctum login itself requires an existing Passport; the contract does not. On the root path there is no parent to attenuate against - the ceremony creates the parent. Consequence. Authority usually decreases down the chain, so compromising a leaf yields no more than that leaf was granted. The guarantee is only as good as the issuing path's discipline, and the paths are not equivalent. Compromising a signing service yields the ability to attest - bounded by whatever that service actually checks - plus the ability to produce a valid fee attestation for a specific token identifier. It still cannot mint without a wallet that pays the fee, and it cannot spend, burn, or transfer existing credentials. See §3 and §6. 2.5 The issuer signs policy, not presentation The issuer's serviceprovider_signature covers a canonical hash of the fields that constrain behaviour and locate the credential: identifier, validity window, rate limits, CIDR and geo constraints, JWT duration, permitted routes, lineage, OpenAPI URL, and the subject's home API URL. It deliberately excludes the distinguished name and the webhook callback URL. Canonicalization is bit-for-bit: keys ordered, values typed as the signer typed them, hashed, then Ed25519. Independent implementations that diverge here fail loudly. Independent implementations that diverge in enforcement fail quietly (§7.2). Consequence. Holders get latitude over cosmetic and operational fields without invalidating the issuer's attestation. The cost is direct: descriptive identity carries no issuer endorsement at all. Cryptography binds a key to an identifier, never to a name, a brand, or an organization. §5.5 develops this. A second, smaller cost: unsigned fields can change nothing on-chain (metadata is immutable), but a verifier that trusts userselected_dn or webhook_url because "the Passport verified" is trusting something the signature never covered. 2.6 Identity may be mortal; it is not required to be Passports can expire. Metadata cannot be renewed or extended in place. Continuing past a real not_after means issuing a new Passport with a new identifier. The contract also accepts 1970-01-01 as an unbounded sentinel on both not_before and not_after . Verifiers treat that sentinel as "no bound". Root and some operational credentials are issued that way. Mortality is therefore a policy choice, not a structural invariant. Consequence. When a real expiry is set, no stale credential accumulates indefinitely, and an immutable credential means a signature that was valid once stays valid without re-attestation. When the sentinel is used, the credential lives until it is destroyed. In either case, identity continuity across replacement is not a system feature - it becomes the holder's problem, solved out-of-band. §7.3. 2.7 Two proof lanes, deliberately not interchangeable The system separates getting a session with a service from proving identity to a peer. | Session lane | Peer lane | | |---|---|---| | Question answered | "May I have a session with this service?" | "Am I who I claim to be, to you?" | | Result | A bearer JWT scoped to one service, carrying policy as claims | A portable HOLA line | | Requires a third party | Yes - that service | No | | Meaningful to anyone else | No | Yes | | Family / login-mode gate | Yes | No | | Freshness | Challenge timestamp, future-dated signatures rejected; maximum age is not enforced | Nonce plus timestamp, maximum age enforced, replay cache on the verifier | Consequence. Each lane can be optimized for its job: sessions are cheap and stateful, peer proofs are se

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.