MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / project

Function project

atomic-canonical/src/prov.rs:134–190  ·  view source on GitHub ↗

Project a turn's provenance into the named-subgraph JSON-LD. Builds `urn:atomic:provgraph: ` with `@graph = [prov:Activity, prov:SoftwareAgent, prov:Person]`, exactly per the doc §"A provenance graph" but with the hard-scope agent-id override (`urn:atomic:agent: `, never a DID) and `used: []` (flywheel deferred). Deterministic: fixed key insertion order + JCS canonicalizati

(input: &ProvActivityInput)

Source from the content-addressed store, hash-verified

132/// Deterministic: fixed key insertion order + JCS canonicalization at sign time
133/// make the signed bytes stable across calls.
134pub fn project(input: &ProvActivityInput) -> Value {
135 let agent_id = agent_urn(&input.agent_slug);
136
137 // --- prov:Activity ---------------------------------------------------
138 let mut activity = Map::new();
139 activity.insert("@type".into(), json!("prov:Activity"));
140 activity.insert("@id".into(), json!(activity_urn(&input.activity_id)));
141 if let Some(started) = &input.started_at {
142 activity.insert("prov:startedAtTime".into(), json!(started));
143 }
144 if let Some(ended) = &input.ended_at {
145 activity.insert("prov:endedAtTime".into(), json!(ended));
146 }
147 // wasAssociatedWith (the agent) / actedOnBehalfOf (the person).
148 activity.insert("associatedWith".into(), json!(agent_id));
149 activity.insert("actedOnBehalfOf".into(), json!(input.person_did));
150 activity.insert("generated".into(), json!(input.generated));
151 // Flywheel `used` edge — emitted only when non-empty (unknown omitted, never
152 // invented). Empty until the capture records structured inputs.
153 if !input.used.is_empty() {
154 activity.insert("used".into(), json!(input.used));
155 }
156 // turnParent — omit the key entirely when there is no parent turn.
157 if let Some(parent) = &input.turn_parent {
158 activity.insert("turnParent".into(), json!(parent));
159 }
160
161 // --- prov:SoftwareAgent (NON-VERIFIABLE descriptive label) -----------
162 let mut agent = Map::new();
163 agent.insert("@type".into(), json!("prov:SoftwareAgent"));
164 agent.insert("@id".into(), json!(agent_id));
165 agent.insert("actedOnBehalfOf".into(), json!(input.person_did));
166 // Human label as rdfs:label (there is no prov:label in PROV-O); the ctx maps
167 // the `label` term to rdfs:label.
168 agent.insert("label".into(), json!(input.agent_display_name));
169 if let Some(vendor) = &input.agent_vendor {
170 agent.insert("vendor".into(), json!(vendor));
171 }
172
173 // --- prov:Person (the real did:atomic signer) ------------------------
174 let mut person = Map::new();
175 person.insert("@type".into(), json!("prov:Person"));
176 person.insert("@id".into(), json!(input.person_did));
177
178 let mut root = Map::new();
179 root.insert("@context".into(), json!(CONTEXT_URL));
180 root.insert("@id".into(), json!(provgraph_urn(&input.change_id_base32)));
181 root.insert(
182 "@graph".into(),
183 json!([
184 Value::Object(activity),
185 Value::Object(agent),
186 Value::Object(person),
187 ]),
188 );
189 Value::Object(root)
190}
191

Callers 6

runMethod · 0.85
print_activity_chainFunction · 0.85
attest_provFunction · 0.85

Calls 3

agent_urnFunction · 0.85
insertMethod · 0.45
is_emptyMethod · 0.45