1 import Base 2 import ./trace_facts.bend as TraceFacts 3 import ./ordinary_schema.bend as Schema 4 import ./ordinary_query_declaration.bend as Query 5 import ./world.bend as W 6 import ./system.bend as Sys 7 import ./resource.bend as Res 8 import ./transaction.bend as T 9 import ./commands.bend as Cmd 10 import ./capabilities.bend as Cap 11 # Static declaration: one ordinary identity supplies operational grant and metadata. 12 # Current resource operations replace the entire Resources owner, not one field. 13 # Retained whole-resource identity, access mode and operational grant. R may be 14 # affine Type; this declaration does not narrow replacement to a selected field. 15 # Raw declaration/adapters remain trusted, rather than authority created by strings. 16 type Declaration<-S:Data,-R:Type,-H:Type,-Ops:Type> is Type: 17 Declaration{identity:Schema.Resource,kind:Query.Mode,grant:Ops} 18 # Build whole-resource read declaration exposing detached V through an owner- 19 # returning projector. This supplies no setter and does not copy the actual R. 20 def read(~S:Data,~C:Type,~R:Type,~E:Data,~V:Data,~project:R -> R & V,identity:Schema.Resource) -> Declaration,E>,Cap.ValueRead,E>,V>>: 21 Declaration{identity,Query.Read{},Cap.ValueRead{Res.tx_get(~S,~C,~R,~E,~V,~project)}} 22 # Build whole-R read/replacement declaration. Setter consumes incoming R and 23 # journals displaced R for ordinary rollback; it returns no recovery receipt. 24 def write(~S:Data,~C:Type,~R:Type,~E:Data,~V:Data,~project:R -> R & V,identity:Schema.Resource) -> Declaration,E>,Cap.ValueWrite,E>,R,V>>: 25 Declaration{identity,Query.Write{},Cap.ValueWrite{Res.tx_get(~S,~C,~R,~E,~V,~project),Res.tx_replace(~S,~C,~R,~E)}} 26 # Advanced declaration projection of operational caps; does not invoke them. 27 def grant(~S:Data,~R:Type,~H:Type,~Ops:Type,declaration:Declaration) -> Ops: 28 match declaration: 29 case Declaration{_,_,grant}:grant 30 # Derive the resource key/mode clause from the same retained declaration. 31 def clause(~S:Data,~R:Type,~H:Type,~Ops:Type,declaration:Declaration) -> Query.Clause: 32 match declaration: 33 case Declaration{identity,kind,_}:Query.Clause{Schema.resource_key(~S,~R,identity),kind} 34 # Project the declared read/write mode without inspecting resource storage. 35 def mode(~S:Data,~R:Type,~H:Type,~Ops:Type,declaration:Declaration) -> Query.Mode: 36 match declaration: 37 case Declaration{_,kind,_}:kind 38 # Description allocation is explicit observation work, not registration work. 39 # Presentation adapter expanding access names into same-mode detached clauses. 40 # Does not validate grants, allocate a registry or invoke a resource operation. 41 def descriptions(~S:Data,+kind:Query.Mode,names:List<&2,String>) -> List<&2,Query.Clause>: 42 match names: 43 case []:[] 44 case name <> rest:Query.Clause{name,kind} <> descriptions(~S,kind,rest) 45 # Project the singleton operational resource name used for registration metadata. 46 def access(~S:Data,value:Query.Clause) -> List<&2,String>: 47 match value: 48 case Query.Clause{name,_}:[name] 49 def returned(~S:Data,~C:Type,~R:Type,~E:Data,~Error:Data,~Out:Type,output:Out,result:T.Returned,Error>) -> Sys.Outcome,Error,Out>: 50 match result: 51 case T.Returned{world,T.Success{}}:Sys.Succeeded{world,output} 52 case T.Returned{world,T.Failure{error}}:Sys.Failed{world,error} 53 def finished(~S:Data,~C:Type,~R:Type,~E:Data,~Error:Data,~Out:Type,result:T.Tx,E> & (T.Outcome & Out)) -> Sys.Outcome,Error,Out>: 54 match result: 55 case (tx,(outcome,output)):returned(~S,~C,~R,~E,~Error,~Out,output,Cmd.tx_finish(~S,~C,~R,~E,~Error,tx,outcome)) 56 # Invoke the opaque-owner body in one fresh ECS transaction with declaration caps. 57 # Args and Out may own Type payloads. Success returns Out; failure rolls back 58 # recorded ECS edits and discards Out. Deferred commands require a later barrier; 59 # ordinary rollback is not owned recovery or reversal of external callback effects. 60 def runner(~S:Data,~C:Type,~R:Type,~E:Data,~Ops:Type -> Type,~Args:Type,~Error:Data,~Out:Type,~declaration:Declaration,E>,Ops(T.Tx,E>)>,~body:@-H:Type -> @-caps:Ops(H) -> Args -> H -> H & (T.Outcome & Out),world:W.World,args:Args) -> Sys.Outcome,Error,Out>: 61 finished(~S,~C,~R,~E,~Error,~Out,Cap.invoke_owned(~Ops,~Args,~(T.Outcome & Out),~body,~T.Tx,E>,~grant(~S,~R,~T.Tx,E>,~Ops(T.Tx,E>),declaration),args,T.begin(~W.World,~E,world))) 62 # Affine registry owner plus presentation slot, indexed by declared access mode. 63 # Resource payload remains in World, not copied into this registration metadata. 64 type Owner<-S:Data,-Registry:Type,-kind:Query.Mode> is Type: 65 Owner{registry:Registry,slot:String} 66 # Registration result returning World in both branches; Defined retains registry 67 # in Owner and Rejected has no newly allocated runner owner. 68 type Defined<-S:Data,-World:Type,-Registry:Type,-kind:Query.Mode> is Type: 69 Defined{world:World,owner:Owner} 70 Rejected{world:World} 71 def registered(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Out:Type,~kind:Query.Mode,~run:W.World -> Args -> Sys.Outcome,Error,Out>,slot:String,result:Sys.RegistrationResult) -> Defined,Sys.Registry,kind>: 72 match result: 73 case Sys.RegistrationFailed{world}:Rejected{world} 74 case Sys.Registered{world,registry}:Defined{world,Owner{registry,slot}} 75 # Register the declaration-bound runner with its derived access. slot is retained 76 # for presentation and does not change operational resource authority. No body runs 77 # at registration. See the named-app matched-feature fixture under test-fixtures. 78 def define(~S:Data,~C:Type,~R:Type,~E:Data,~Ops:Type -> Type,~Args:Type,~Error:Data,~Out:Type,~declaration:Declaration,E>,Ops(T.Tx,E>)>,~body:@-H:Type -> @-caps:Ops(H) -> Args -> H -> H & (T.Outcome & Out),world:W.World,name:String,slot:String) -> Defined,Sys.Registry,mode(~S,~R,~T.Tx,E>,~Ops(T.Tx,E>),declaration)>: 79 registered(~S,~C,~R,~E,~Args,~Error,~Out,~mode(~S,~R,~T.Tx,E>,~Ops(T.Tx,E>),declaration),~runner(~S,~C,~R,~E,~Ops,~Args,~Error,~Out,~declaration,~body),slot,Sys.register(~S,~C,~R,~E,~Args,~Error,~Out,~runner(~S,~C,~R,~E,~Ops,~Args,~Error,~Out,~declaration,~body),world,name,access(~S,clause(~S,~R,~T.Tx,E>,~Ops(T.Tx,E>),declaration)))) 80 # Registry's existing namespace and registration checks remain authoritative. 81 # Run tracked registration, returning its full success/refusal result plus slot. 82 # Refusal retains actual registry, World and Args under Sys.RunResult; successful 83 # execution returns callback Out, while callback failure does not return Out. 84 def run(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Out:Type,~kind:Query.Mode,~runner:W.World -> Args -> Sys.Outcome,Error,Out>,owner:Owner,kind>,world:W.World,args:Args) -> Sys.RunResult & String: 85 match owner: 86 case Owner{registry,slot}:(Sys.run(~S,~C,~R,~E,~Args,~Error,~Out,~runner,registry,world,args),slot) 87 88 # Called by an enabled debug bridge; actual Registry is borrowed and reconstructed. 89 # Enabled-observation adapter returning actual Owner and detached access clauses. 90 # Does not inspect resource payloads or grant access from the presentation slot. 91 def describe(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Out:Type,~kind:Query.Mode,~runner:W.World -> Args -> Sys.Outcome,Error,Out>,owner:Owner,kind>) -> Owner,kind> & List<&2,Query.Clause>: 92 match owner: 93 case Owner{Sys.Registry{namespace,id,name,+access,cursor},slot}: 94 (Owner{Sys.Registry{namespace,id,name,access,cursor},slot},descriptions(~S,kind,access)) 95 96 def returned_observed(~S:Data,~C:Type,~R:Type,~E:Data,~Error:Data,~Out:Type,output:Out,result:T.Returned,Error> & TraceFacts.State) -> Sys.Outcome,Error,Out> & TraceFacts.State: 97 match result: 98 case (value,trace):(returned(~S,~C,~R,~E,~Error,~Out,output,value),trace) 99 # Same user body and grants, with detached transaction facts returned beside it. 100 # Advanced runner finish adapter retaining detached transaction facts separately 101 # from World outcome. Same commit/rollback and failure-Out disposal as runner; 102 # attempted facts are not evidence that failed transaction writes committed. 103 def finished_observed(~S:Data,~C:Type,~R:Type,~E:Data,~Error:Data,~Out:Type,result:T.Tx,E> & (T.Outcome & Out)) -> Sys.Outcome,Error,Out> & TraceFacts.State: 104 match result: 105 case (tx,(outcome,output)):returned_observed(~S,~C,~R,~E,~Error,~Out,output,T.finish_observed(~W.World,~E,~Error,~Cmd.enqueue(~S,~C,~R,~E),~Cmd.publish(~S,~C,~R,~E),tx,outcome))