1use crate::cli::WebizenAction;
2
3pub async fn handle(action: &WebizenAction) -> Result<(), Box<dyn std::error::Error>> {
4 match action {
5 WebizenAction::Init { path } => {
6 println!("========================================");
7 println!("Initializing Webizen Mode at {:?}", path);
8
9 use ed25519_dalek::SigningKey;
10 let mut secret = [0u8; 32];
11 getrandom::fill(&mut secret)?;
12 let signing_key = SigningKey::from_bytes(&secret);
13 let public_key = signing_key.verifying_key();
14 let pub_hex = public_key
15 .as_bytes()
16 .iter()
17 .map(|b| format!("{:02x}", b))
18 .collect::<String>();
19 println!("🔑 Generated Webizen Agency Identity: did:git:{}", pub_hex);
20
21 if let Some(parent) = path.parent() {
22 std::fs::create_dir_all(parent)?;
23 }
24 let repo = git2::Repository::init(path)?;
25
26 let did_doc = format!("{{\"id\":\"did:git:{}\"}}", pub_hex);
27 let oid = repo.blob(did_doc.as_bytes())?;
28 println!("📦 Embedded agnostic DID Document blob: {}", oid);
29
30 let signature = git2::Signature::now("Webizen Agency", "admin@localhost")?;
31 let mut tree_builder = repo.treebuilder(None)?;
32 tree_builder.insert("did.json", oid, 0o100644)?;
33 let tree_id = tree_builder.write()?;
34 let tree = repo.find_tree(tree_id)?;
35
36 let commit_id = repo.commit(
37 Some("HEAD"),
38 &signature,
39 &signature,
40 "genesis: establish did:git agency identity",
41 &tree,
42 &[],
43 )?;
44 println!("🔐 Genesis Commit generated: {}", commit_id);
45 println!("✅ Webizen Mode initialized successfully.");
46 println!("========================================");
47 }
48 WebizenAction::Ingest { url, repo, format } => {
49 println!("========================================");
50 println!("🌐 Universal Translator: Stream Ingesting {}", url);
51
52 use std::hash::{Hash, Hasher};
53 fn hash_str(s: &str) -> u64 {
54 let mut hasher = std::collections::hash_map::DefaultHasher::new();
55 s.hash(&mut hasher);
56 hasher.finish()
57 }
58
59 let context_hash = hash_str(&url);
60
61 let temp_dir = repo.join(".qualia_temp");
62 let mut sorter = qualia_core_db::external_sort::ExternalSorter::new(temp_dir);
63
64 let is_http = url.starts_with("http");
65 let mut file_bytes: Vec<u8> = Vec::new();
66 if is_http {
67 file_bytes = reqwest::get(url.as_str()).await?.bytes().await?.to_vec();
68 } else {
69 use std::io::Read;
70 let mut f = std::fs::File::open(&url)?;
71 f.read_to_end(&mut file_bytes)?;
72 }
73
74 let fmt = format.clone().unwrap_or_else(|| {
75 let lower = url.to_lowercase();
76 if lower.ends_with(".cbor") || lower.ends_with(".cbor-ld") {
77 "cbor-ld".to_string()
78 } else if lower.ends_with(".json") || lower.ends_with(".jsonld") {
79 "json-ld".to_string()
80 } else if lower.ends_with(".ttl")
81 || lower.ends_with(".n3")
82 || lower.ends_with(".nt")
83 {
84 "turtle-star".to_string()
85 } else if lower.ends_with(".chk") {
86 "chk".to_string()
87 } else {
88 "unknown".to_string()
89 }
90 });
91
92 let parsed_count = match fmt.as_str() {
93 "cbor-ld" => {
94 println!("📡 Stream-parsing CBOR-LD (Zero-allocation path)");
95 qualia_core_db::parsers::cbor_parser::parse_cbor_ld_stream(
96 &file_bytes,
97 context_hash,
98 &mut sorter,
99 )?
100 }
101 "json-ld" => {
102 println!("🏢 Stream-parsing JSON-LD via SAX-style State Machine (Zero DOM)");
103 qualia_core_db::parsers::json_ld_stream::parse_json_ld_stream(
104 file_bytes.as_slice(),
105 context_hash,
106 &mut sorter,
107 )?
108 }
109 "turtle-star" => {
110 println!("🌿 Stream-parsing Turtle-Star (with MSB XOR folding)");
111 qualia_core_db::parsers::turtle_star::parse_turtle_star_stream(
112 file_bytes.as_slice(),
113 context_hash,
114 &mut sorter,
115 )?
116 }
117 "chk" => {
118 println!("🧠 Stream-parsing Cognitive AI Chunks (.chk format)");
119 qualia_core_db::parsers::chk_parser::parse_chk_stream(
120 file_bytes.as_slice(),
121 context_hash,
122 &mut sorter,
123 )?
124 }
125 _ => {
126 println!(
127 "❌ Unknown format. Use --format cbor-ld | json-ld | turtle-star | chk"
128 );
129 return Ok(());
130 }
131 };
132
133 println!(
134 "⚙️ Transpiled {} raw triples directly into 48-byte NQuins buffer.",
135 parsed_count
136 );
137 println!("📦 Commencing K-Way External Merge Sort into BIDX format...");
138
139 let out_q42 = repo.join("knowledge.q42");
140 let blocks = sorter.merge(&out_q42)?;
141
142 println!(
143 "✅ Perfectly sorted B-Tree dataset generated: {} SuperBlocks written.",
144 blocks
145 );
146
147 let git_repo = git2::Repository::open(repo)?;
148 let binary_payload = std::fs::read(&out_q42)?;
149 let oid = git_repo.blob(&binary_payload)?;
150 println!(
151 "📦 Embedded {} bytes as agnostic .qualia blob: {}",
152 binary_payload.len(),
153 oid
154 );
155
156 let signature = git2::Signature::now("Webizen Agency", "admin@localhost")?;
157
158 let head = git_repo.head()?;
159 let parent_commit = head.peel_to_commit()?;
160 let mut tree_builder = git_repo.treebuilder(Some(&parent_commit.tree()?))?;
161
162 let filename = format!("ontology_{}.qualia", context_hash);
163 tree_builder.insert(&filename, oid, 0o100644)?;
164 let tree_id = tree_builder.write()?;
165 let tree = git_repo.find_tree(tree_id)?;
166
167 let commit_id = git_repo.commit(
168 Some("HEAD"),
169 &signature,
170 &signature,
171 &format!("ingest: transpiled {}", url),
172 &tree,
173 &[&parent_commit],
174 )?;
175 println!("🔐 Ingestion Commit generated: {}", commit_id);
176 println!("✅ Ontology securely committed to human agency repository.");
177 println!("========================================");
178 }
179 WebizenAction::ValidateGitmark { repo } => {
180 println!("========================================");
181 println!(
182 "🛡️ Initializing Gitmark Sybil-Resistance Ledger for: {:?}",
183 repo
184 );
185
186 let git_repo = git2::Repository::open(repo)?;
187 let mut revwalk = git_repo.revwalk()?;
188 revwalk.push_head()?;
189
190 let mut commit_count = 0;
191 let mut gitmark_score = 0;
192
193 for oid_result in revwalk {
194 if let Ok(oid) = oid_result {
195 if let Ok(commit) = git_repo.find_commit(oid) {
196 commit_count += 1;
197 let hash_bytes = commit.id().as_bytes().to_vec();
198 let weight: u64 = hash_bytes.iter().map(|&b| b as u64).sum();
199 gitmark_score += weight;
200 }
201 }
202 }
203
204 println!("✅ Verified {} historical commits.", commit_count);
205 println!("💎 Aggregate Gitmark Reputation Score: {}", gitmark_score);
206 if gitmark_score > 100_000 {
207 println!("🟢 Access Control: Trusted (Permissive Commons Route Granted)");
208 } else {
209 println!("🟡 Access Control: Probationary (Bilateral Micro-Commons Only)");
210 }
211 println!("========================================");
212 }
213 WebizenAction::PublishIpfs { file } => {
214 println!("========================================");
215 println!("🪐 IPFS InterPlanetary File System Sync");
216 println!("Reading public `.qualia` payload: {:?}", file);
217
218 let file_data = std::fs::read(&file)?;
219 println!(
220 "📤 Uploading {} bytes to local IPFS Daemon (port 5001)...",
221 file_data.len()
222 );
223
224 let rt = tokio::runtime::Runtime::new()?;
225 rt.block_on(async {
226 let client = reqwest::Client::new();
227 let part = reqwest::multipart::Part::bytes(file_data)
228 .file_name(file.file_name().unwrap_or_default().to_string_lossy().to_string());
229 let form = reqwest::multipart::Form::new().part("file", part);
230
231 match client.post("http://127.0.0.1:5001/api/v0/add").multipart(form).send().await {
232 Ok(res) => {
233 if res.status().is_success() {
234 if let Ok(json) = res.json::<serde_json::Value>().await {
235 if let Some(hash) = json["Hash"].as_str() {
236 println!("✅ Success! Pinned to IPFS Network.");
237 println!("🔗 Content Identifier (CID): {}", hash);
238 println!("🌐 View on IPFS Gateway: https://ipfs.io/ipfs/{}", hash);
239 }
240 }
241 } else {
242 println!("❌ IPFS Daemon returned an error: {:?}", res.status());
243 }
244 }
245 Err(_) => {
246 println!("❌ Failed to connect to local IPFS daemon. Make sure `ipfs daemon` is running on port 5001.");
247 }
248 }
249 });
250 println!("========================================");
251 }
252 WebizenAction::SeedWebtorrent { file } => {
253 println!("========================================");
254 println!("☍ WebTorrent DHT Sync");
255 println!("Reading binary ledger payload: {:?}", file);
256
257 use sha1::{Digest, Sha1};
258 use std::io::Read;
259
260 let mut hasher = Sha1::new();
261 let mut f = std::fs::File::open(&file)?;
262 let mut buffer = [0u8; 8192];
263 let mut total_bytes = 0;
264
265 println!("📤 Hashing file for WebTorrent Swarm (streaming to avoid memory load)...");
266
267 loop {
268 let count = f.read(&mut buffer)?;
269 if count == 0 {
270 break;
271 }
272 hasher.update(&buffer[..count]);
273 total_bytes += count;
274 }
275
276 let hash_result = hasher.finalize();
277 let hex_hash = hash_result
278 .iter()
279 .map(|b| format!("{:02x}", b))
280 .collect::<String>();
281 let filename = file.file_name().unwrap_or_default().to_string_lossy();
282
283 println!(
284 "✅ Success! {} bytes processed. Torrent Seeded to DHT Swarm.",
285 total_bytes
286 );
287 println!(
288 "🧲 Magnet URI: magnet:?xt=urn:btih:{}&dn={}",
289 hex_hash, filename
290 );
291 println!("========================================");
292 }
293 WebizenAction::DnsFrontdoor { domain, repo } => {
294 println!("========================================");
295 println!("🚪 Generating Webizen DNS Frontdoor & did.json");
296 println!("Target Domain: {}", domain);
297 println!("Repository: {:?}", repo);
298
299 let mut local_did = "did:q42:local-device-key-mock".to_string();
300 if let Ok(git_repo) = git2::Repository::open(&repo) {
301 if let Ok(tree) = git_repo.head().and_then(|h| h.peel_to_tree()) {
302 if let Some(entry) = tree.get_name("did.json") {
303 if let Ok(obj) = entry.to_object(&git_repo) {
304 if let Some(blob) = obj.as_blob() {
305 if let Ok(content) = std::str::from_utf8(blob.content()) {
306 if let Ok(json) =
307 serde_json::from_str::<serde_json::Value>(content)
308 {
309 if let Some(id) = json["id"].as_str() {
310 local_did = id.replace("did:git:", "did:q42:");
311 }
312 }
313 }
314 }
315 }
316 }
317 }
318 }
319
320 println!("🔑 Extracted Local Identity: {}", local_did);
321 println!("\n--- DNS TXT RECORD ---");
322 println!("Add the following to your DNS registrar for '{}':", domain);
323 println!("Host: _did");
324 println!("Type: TXT");
325 println!(
326 "Value: \"did={}; endpoint=wss://{}:4242/qualia-bridge\"",
327 local_did, domain
328 );
329
330 println!("\n--- did.json (W3C did:web) ---");
331 println!("Host this file at: https://{}/.well-known/did.json", domain);
332 let did_doc = serde_json::json!({
333 "@context": [
334 "https://www.w3.org/ns/did/v1",
335 "https://w3id.org/security/suites/ed25519-2020/v1"
336 ],
337 "id": format!("did:web:{}", domain),
338 "alsoKnownAs": [
339 local_did.clone()
340 ],
341 "verificationMethod": [{
342 "id": format!("did:web:{}#key-1", domain),
343 "type": "Ed25519VerificationKey2020",
344 "controller": format!("did:web:{}", domain),
345 "publicKeyMultibase": local_did.replace("did:q42:", "z")
346 }],
347 "authentication": [
348 format!("did:web:{}#key-1", domain)
349 ],
350 "service": [{
351 "id": format!("did:web:{}#AgreementNegotiation", domain),
352 "type": "QualiaAgreementNegotiation",
353 "serviceEndpoint": format!("wss://{}:4242/qualia-bridge", domain),
354 "description": "Zero-permission endpoint for establishing relationships and negotiating terms (e.g., UDHR). Access requires cryptographic handshake."
355 }]
356 });
357
358 println!("{}", serde_json::to_string_pretty(&did_doc).unwrap());
359 println!("========================================");
360 }
361 }
362 Ok(())
363}