// Package draft illustrates BOTH peers. It is not a device driver or security library. // BeginVerified must authenticate/authorise/bind the proof and acquire an atomic // transaction. Close rolls back unless committed; cached USE must not actuate again. package draft import "errors" type Op string const (Register Op = "REGISTER"; Use Op = "USE"; Revoke Op = "REVOKE"; Retract Op = "RETRACT") type Envelope struct { Fields []string; Signature string } type Result struct { Receipt Envelope; Fresh bool } type Tx interface { Operation() Op Cached() *Envelope RegisterNewKey() error RequireCurrentEntitlement() error RevokeTarget() error RetractRelationship() error SignResult() (Envelope, error) CommitOnce(Envelope) error Close() } type Ports interface { Challenge(Op, string, string, string) (Envelope,error) VerifyProviderAndApprove(Envelope) error SignProof(Envelope) (Envelope,error) VerifyResultAndApply(Envelope) error BeginVerified(Envelope,string) (Tx,error) RecoverRevoke(string,string,string) (Envelope,error) } type TokenSide struct { Ports Ports } func(t TokenSide) Respond(q Envelope)(Envelope,error){ if err:=t.Ports.VerifyProviderAndApprove(q);err!=nil{return Envelope{},err} return t.Ports.SignProof(q) } func(t TokenSide) Accept(r Envelope)error{return t.Ports.VerifyResultAndApply(r)} type ProviderSide struct { Ports Ports } func(p ProviderSide) Start(op Op,rid,target,context string)(Envelope,error){ return p.Ports.Challenge(op,rid,target,context) } func(p ProviderSide) Finish(proof Envelope,context string)(Result,error){ tx,err:=p.Ports.BeginVerified(proof,context);if err!=nil{return Result{},err};defer tx.Close() if old:=tx.Cached();old!=nil{return Result{*old,false},nil} switch tx.Operation(){ case Register: err=tx.RegisterNewKey() case Use: err=tx.RequireCurrentEntitlement() case Revoke: err=tx.RevokeTarget() case Retract: err=tx.RetractRelationship() default: err=errors.New("unsupported operation") } if err!=nil{return Result{},err} receipt,err:=tx.SignResult();if err!=nil{return Result{},err} if err=tx.CommitOnce(receipt);err!=nil{return Result{},err} return Result{receipt,true},nil } func(p ProviderSide) Lost(rid,target,context string)(Envelope,error){return p.Ports.RecoverRevoke(rid,target,context)} func LegacyValue(value string,approved,selected bool)(string,error){ if !approved||!selected||value==""{return "",errors.New("local approval/selection required")} return value,nil // No BringPass command crosses the legacy boundary. }