What
Make L2PS subnet membership map to CCI primary claims via an anchored binding proof. Today L2PS identifies members by RSA keys; DACS-3 needs members identified by their CCI ClaimReference (CH-1, CH-3 of §8.3.1).
Why
Until L2PS is natively CCI-keyed, DACS-3 §8.3.2 specifies an interim binding-proof anchored via SR-2 (Storage Programs). Without it, in-channel signatures prove nothing about on-chain identity, and negotiate-rfq / negotiate-sealed-envelope cannot satisfy the conformance bar.
Scope (in sdks/src/l2ps/binding/)
type L2PSMembershipBinding = {
bindingVersion: "1"
channelId: string // the L2PS subnet / session channel id
subnetMemberId: string // the member's L2PS/RSA identity within the subnet
cciPrimaryClaim: ClaimReference // from WI-0
boundAt: number // unix ms
signature: string // CCI-primary-key sig over canonical(binding minus signature)
}
// Public API:
export async function createMembershipBinding(
channelId: string,
subnetMemberId: string,
claim: ClaimReference,
demos: Demos,
): Promise<L2PSMembershipBinding>
export async function anchorMembershipBinding(
binding: L2PSMembershipBinding,
demos: Demos,
): Promise<{ storageProgramId: string }> // SR-2 anchor
export async function resolveMember(
channelId: string,
subnetMemberId: string,
demos: Demos,
): Promise<ClaimReference | null> // null if no valid binding
export function verifyMembershipBinding(b: L2PSMembershipBinding): boolean
Signing rule
signed_bytes := "dacs-binding:v1:" || sha256(canonical_JCS(binding_without_signature)) — signed with signWithPrimaryClaim from WI-0. Reject any binding whose signature was produced by the RSA subnet key (the whole point of this work item).
Anchoring
- Each binding lives in its own Storage Program OR a shared SP keyed by
(channelId, subnetMemberId). Pick the simpler one — the brief leaves layout to us.
- Anchor MUST happen before negotiation starts.
resolveMember reads the anchored binding back via the SR-2 chain query.
- Membership is fixed for channel lifetime (CH-1). No mutation API.
Acceptance
Dependencies
- Blocked by WI-0 (ClaimReference + signWithPrimaryClaim).
- Consumes existing
@kynesyslabs/demosdk/storage for the SR-2 anchor.
Source
Brief §2 WI-1 + DACS-3 §8.3.2.
What
Make L2PS subnet membership map to CCI primary claims via an anchored binding proof. Today L2PS identifies members by RSA keys; DACS-3 needs members identified by their CCI
ClaimReference(CH-1, CH-3 of §8.3.1).Why
Until L2PS is natively CCI-keyed, DACS-3 §8.3.2 specifies an interim binding-proof anchored via SR-2 (Storage Programs). Without it, in-channel signatures prove nothing about on-chain identity, and
negotiate-rfq/negotiate-sealed-envelopecannot satisfy the conformance bar.Scope (in
sdks/src/l2ps/binding/)Signing rule
signed_bytes := "dacs-binding:v1:" || sha256(canonical_JCS(binding_without_signature))— signed withsignWithPrimaryClaimfrom WI-0. Reject any binding whose signature was produced by the RSA subnet key (the whole point of this work item).Anchoring
(channelId, subnetMemberId). Pick the simpler one — the brief leaves layout to us.resolveMemberreads the anchored binding back via the SR-2 chain query.Acceptance
resolveMember(channelId, subnetMemberId)returns the boundClaimReference; returnsnullfor unknown member.subnet member ↔ CCI primary claim ↔ DACS-1 bundlefor every member (DACS-1 bundle verification stays out of scope — we just expose the ClaimReference).subnetMemberIdwithout a valid binding is rejected by the WI-2 envelope verifier (test added in WI-2; cross-link).Dependencies
@kynesyslabs/demosdk/storagefor the SR-2 anchor.Source
Brief §2 WI-1 + DACS-3 §8.3.2.