@ibgib/space-gib 0.0.21 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -165,19 +165,19 @@
165
165
  </header>
166
166
 
167
167
  <main>
168
- <h1 class="policy-title">Privacy Policy</h1>
169
- <p><strong>Status</strong>: DRAFT (Active Development) </p>
170
- <p><strong>Effective Date</strong>: August 21, 2026 </p>
171
- <p><strong>Last Updated</strong>: August 21, 2026 </p>
168
+ <h1 id="privacypolicy" class="policy-title">Privacy Policy</h1>
169
+ <p><strong>Status</strong>: DRAFT (Active Development)</p>
170
+ <p><strong>Effective Date</strong>: August 21, 2026</p>
171
+ <p><strong>Last Updated</strong>: August 21, 2026</p>
172
172
  <div class="alert-box alert-warning"><div class="alert-icon">⚠️</div><div class="alert-body"><strong>Draft Notice &amp; Active Development Disclaimer</strong>:<br>This Privacy Policy is currently in <strong>draft status</strong>. The <code>ibGib</code> platform, underlying cryptographic keystone engine, and decentralized data graph architecture are under <strong>active research and development</strong>. This document expresses our architectural intent, privacy commitments, and operational principles; however, as the technology is actively evolving, certain features, administrative tooling, and data workflows described herein may be experimental, partially implemented, or subject to change.</div></div>
173
173
  <hr class="divider">
174
- <h2 class="policy-h2">1. Introduction &amp; Overview</h2>
175
- <p>Welcome to <strong>ibGib</strong>. We are committed to transparency, cryptographic self-sovereignty, and user privacy. </p>
176
- <p>This Privacy Policy explains how <code>ibGib</code> (including <code>ibgib.space</code>, <code>ibgib.com</code>, and related open-source applications in this monorepo) collects, uses, stores, and protects your information when you interact with our network, services, and applications. </p>
174
+ <h2 id="1introductionovervie" class="policy-h2">1. Introduction &amp; Overview</h2>
175
+ <p>Welcome to <strong>ibGib</strong>. We are committed to transparency, cryptographic self-sovereignty, and user privacy.</p>
176
+ <p>This Privacy Policy explains how <code>ibGib</code> (including <code>ibgib.space</code>, <code>ibgib.com</code>, and related open-source applications in this monorepo) collects, uses, stores, and protects your information when you interact with our network, services, and applications.</p>
177
177
  <div class="alert-box alert-important"><div class="alert-icon">ℹ️</div><div class="alert-body"><strong>Summary for Everyone</strong>:<br>* <strong>Public Directory</strong>: Just like a public PGP key or public DNS record, your chosen <strong>username</strong>, <strong>registered email address</strong>, and <strong>identity keystone</strong> are part of the public graph so people and your devices can find and authenticate you.<br>* <strong>No Passwords on the Wire</strong>: Your master passphrase, biometric data (Touch ID / Face ID / Windows Hello), and physical security keys (YubiKeys) <strong>never</strong> leave your local device.<br>* <strong>No Data Selling</strong>: We do <strong>not</strong> sell, rent, monetize, or share your personal data with third-party advertisers or data brokers.<br>* <strong>Standard Transport Security</strong>: All communications between your devices and our servers operate over industry-standard <strong>TLS 1.3 / HTTPS</strong> encryption.</div></div>
178
178
  <hr class="divider">
179
- <h2 class="policy-h2">2. Categories of Information We Collect</h2>
180
- <h3 class="policy-h3">A. Identity &amp; Public Directory Data</h3>
179
+ <h2 id="2categoriesofinforma" class="policy-h2">2. Categories of Information We Collect</h2>
180
+ <h3 id="aidentitypublicdirec" class="policy-h3">A. Identity &amp; Public Directory Data</h3>
181
181
  <p>When you create an account or link authentication methods, the following information is recorded in your identity keystone:</p>
182
182
  <ul>
183
183
  <li><strong>Chosen Username</strong>: A human-readable identifier (e.g. <code>alice</code>).</li>
@@ -185,7 +185,7 @@
185
185
  <li><strong>Public Keystone DAG Addresses &amp; Challenge Hashes</strong>: Cryptographic addresses and mathematical challenge hashes (<code class="math">H = \text{Hash}(S)</code>) that define your identity's evolution timeline.</li>
186
186
  <li><strong>Registered Device Delegate Tags</strong>: Public labels for devices authorized to sync on your behalf (e.g. <code>pwd-alice-desk-a9a0</code>, <code>passkey-mobile-b4c1</code>).</li>
187
187
  </ul>
188
- <h3 class="policy-h3">B. Technical, Connection &amp; Log Data</h3>
188
+ <h3 id="btechnicalconnection" class="policy-h3">B. Technical, Connection &amp; Log Data</h3>
189
189
  <p>When accessing our hosted web nodes, standard operational connection data may be logged:</p>
190
190
  <ul>
191
191
  <li><strong>Internet Protocol (IP) Address</strong> and approximate geographic origin.</li>
@@ -193,15 +193,15 @@
193
193
  <li><strong>User-Agent Strings</strong>: Browser type, operating system, and client application version.</li>
194
194
  <li><strong>Retention</strong>: Operational and access logs are retained for a bounded window (typically <strong>30 to 90 days</strong>) strictly for system reliability, rate limiting, intrusion detection, and security forensics, after which they are automatically rotated and deleted.</li>
195
195
  </ul>
196
- <h3 class="policy-h3">C. Workspace &amp; Application Data</h3>
196
+ <h3 id="cworkspaceapplicatio" class="policy-h3">C. Workspace &amp; Application Data</h3>
197
197
  <ul>
198
198
  <li><strong>User-Created Content</strong>: Notes, comments, graph nodes, and files stored within your tenant workspace.</li>
199
199
  <li><strong>Storage Status</strong>: Workspace data is stored in tenant-isolated domain spaces. Data in transit is encrypted via TLS 1.3. Data at rest on the server is currently stored unencrypted within your isolated space directory (client-side data encryption is planned as a future capability).</li>
200
200
  </ul>
201
201
  <hr class="divider">
202
- <h2 class="policy-h2">3. Public Directory Nature of Identity Keystones</h2>
203
- <div class="alert-box alert-warning"><div class="alert-icon">⚠️</div><div class="alert-body"><strong>Experimental Architecture Notice</strong>:<br>Identity Keystones are built on an innovative Zero-Knowledge Proof (ZKP) Distributed Ledger Technology (DLT) architecture. While designed to eliminate reliance on central certificate authorities, this technology is experimental. See <a href="#7-security-architecture--experimental-protocol-notice" target="_blank" rel="noopener">Section 7</a> for detailed security context.</div></div>
204
- <h3 class="policy-h3">Innovative ZKP DLT vs. Conventional PKI</h3>
202
+ <h2 id="3publicdirectorynatu" class="policy-h2">3. Public Directory Nature of Identity Keystones</h2>
203
+ <div class="alert-box alert-warning"><div class="alert-icon">⚠️</div><div class="alert-body"><strong>Experimental Architecture Notice</strong>:<br>Identity Keystones are built on an innovative Zero-Knowledge Proof (ZKP) Distributed Ledger Technology (DLT) architecture. While designed to eliminate reliance on central certificate authorities, this technology is experimental. See <a href="#7securityarchitectur">Section 7</a> for detailed security context.</div></div>
204
+ <h3 id="innovativezkpdltvsco" class="policy-h3">Innovative ZKP DLT vs. Conventional PKI</h3>
205
205
  <p><code>ibGib</code> is built upon public-key cryptographic principles, but <strong>is not conventional Public Key Infrastructure (PKI)</strong>:</p>
206
206
  <ul>
207
207
  <li>Instead of relying on asymmetric digital signatures (RSA, ECDSA) and centralized X.509 Certificate Authorities (CAs), <code>ibGib</code> identities utilize a <strong>Zero-Knowledge Proof (ZKP) Distributed Ledger Technology (DLT)</strong> architecture with symmetric hash-reveal challenge-response pools.</li>
@@ -212,7 +212,7 @@
212
212
  <li>Hardware biometrics (fingerprints, facial recognition) and security keys operate exclusively within your device's hardware Secure Enclave / TPM via the W3C WebAuthn standard. Raw biometric data is never transmitted over the network or accessible to our servers.</li>
213
213
  </ul>
214
214
  <hr class="divider">
215
- <h2 class="policy-h2">4. How We Use Your Information</h2>
215
+ <h2 id="4howweuseyourinforma" class="policy-h2">4. How We Use Your Information</h2>
216
216
  <p>We process personal and cryptographic data solely for the following legitimate purposes:</p>
217
217
  <ol>
218
218
  <li><strong>Identity Resolution &amp; Discovery</strong>: Matching incoming authentication requests and email lookups to the correct tenant domain space.</li>
@@ -222,7 +222,7 @@
222
222
  </ol>
223
223
  <p>We do <strong>not</strong> use your data for profiling, automated decision-making, or third-party targeted advertising.</p>
224
224
  <hr class="divider">
225
- <h2 class="policy-h2">5. Third-Party Service Providers</h2>
225
+ <h2 id="5third-partyservicep" class="policy-h2">5. Third-Party Service Providers</h2>
226
226
  <p>We utilize minimal third-party services essential to core platform functionality:</p>
227
227
  <ul>
228
228
  <li><strong>Single Sign-On (SSO) Authentication (Optional)</strong>:</li>
@@ -233,29 +233,29 @@
233
233
  <li><strong>Cloud Server &amp; Storage Nodes</strong>: Web nodes, domain space storage, and network routing are hosted on secure cloud infrastructure located in the United States.</li>
234
234
  </ul>
235
235
  <hr class="divider">
236
- <h2 class="policy-h2">6. Immutable Timeline Integrity, Revocations &amp; Data Deletion</h2>
237
- <h3 class="policy-h3">Cryptographic Timeline Integrity</h3>
236
+ <h2 id="6immutabletimelinein" class="policy-h2">6. Immutable Timeline Integrity, Revocations &amp; Data Deletion</h2>
237
+ <h3 id="cryptographictimelin" class="policy-h3">Cryptographic Timeline Integrity</h3>
238
238
  <p><code>ibGib</code> is built on an <strong>append-only, directed acyclic graph (DAG) architecture</strong>. Similar to version control systems (like Git) and cryptographic ledgers (like Bitcoin), timeline records are mathematically linked using cryptographic hashes to ensure data integrity and tamper-evidence. Just as past blocks in a blockchain cannot be modified without destroying cryptographic integrity, historical keystone frames remain part of the verifiable audit chain.</p>
239
- <h3 class="policy-h3">Revocations &amp; Tombstones</h3>
239
+ <h3 id="revocationstombstone" class="policy-h3">Revocations &amp; Tombstones</h3>
240
240
  <p>When you modify your identity permissions—such as unlinking a Google SSO provider or revoking a lost device passkey:</p>
241
241
  <ul>
242
242
  <li>The system publishes a cryptographically signed <strong>tombstone evolution frame</strong> (<code class="math">n \to n+1</code>).</li>
243
243
  <li>This frame officially revokes that authority and unlinks the provider from server-side reverse lookup indices.</li>
244
244
  </ul>
245
- <h3 class="policy-h3">Content Takedowns &amp; Full Account Erasure</h3>
245
+ <h3 id="contenttakedownsfull" class="policy-h3">Content Takedowns &amp; Full Account Erasure</h3>
246
246
  <ol>
247
247
  <li><strong>Content &amp; Asset Takedowns</strong>: Standalone content nodes and binary file payloads can be unlinked, de-indexed, or removed from server storage upon authorized request or valid legal takedown without compromising structural timeline history.</li>
248
248
  <li><strong>Complete Tenant Erasure</strong>: If you request complete account deletion, your entire tenant domain space (including all hosted keystones, delegate frames, and stored data) and reverse email index entries will be permanently purged and removed from server storage.</li>
249
249
  <li><strong>Local Device Data Control</strong>: You maintain full control over all data stored locally on your physical devices. You may clear your local cryptographic tokens, delegates, and cached workspace data at any time via the application settings or by clearing your browser's IndexedDB / local storage.</li>
250
250
  </ol>
251
251
  <hr class="divider">
252
- <h2 class="policy-h2">7. Security Architecture &amp; Experimental Protocol Notice</h2>
253
- <h3 class="policy-h3">Innovative &amp; Experimental Nature</h3>
252
+ <h2 id="7securityarchitectur" class="policy-h2">7. Security Architecture &amp; Experimental Protocol Notice</h2>
253
+ <h3 id="innovativeexperiment" class="policy-h3">Innovative &amp; Experimental Nature</h3>
254
254
  <p>Identity Keystones, multi-pool challenge-response mechanisms, and decentralized sync delegates represent innovative, experimental cryptographic protocols. While we apply diligent best efforts in cryptanalysis and utilize industry-standard, proven cryptographic primitives (such as SHA-256, SHA-512, AES, and WebAuthn PRF), the composite architecture is actively evolving. Users should evaluate this platform understanding its experimental research nature.</p>
255
- <h3 class="policy-h3">Conventional Security Foundations</h3>
255
+ <h3 id="conventionalsecurity" class="policy-h3">Conventional Security Foundations</h3>
256
256
  <p>All communications, API endpoints, and authentication exchanges between your client devices and our server infrastructure operate strictly over industry-standard <strong>TLS 1.3 / HTTPS</strong> encryption. Server-side data isolation, atomic file indexing, and timing side-channel protections are implemented following standard enterprise security practices.</p>
257
257
  <hr class="divider">
258
- <h2 class="policy-h2">8. Your Privacy Rights (Texas TDPSA &amp; US State Privacy Laws)</h2>
258
+ <h2 id="8yourprivacyrightste" class="policy-h2">8. Your Privacy Rights (Texas TDPSA &amp; US State Privacy Laws)</h2>
259
259
  <p>If you are a resident of Texas (governed by the <strong>Texas Data Privacy and Security Act - TDPSA</strong>) or other jurisdictions with applicable privacy legislation, you have the following rights regarding your personal data:</p>
260
260
  <ul>
261
261
  <li><strong>Right to Know / Access</strong>: You have the right to confirm whether we process your personal data and to access such data.</li>
@@ -265,23 +265,23 @@
265
265
  <li><strong>Right to Opt-Out of Sale / Targeted Advertising</strong>: We do <strong>not</strong> sell your personal data or process it for targeted advertising, so no opt-out is necessary.</li>
266
266
  <li><strong>Right to Non-Discrimination</strong>: We will never discriminate against you, deny services, or alter pricing for exercising your privacy rights.</li>
267
267
  </ul>
268
- <h3 class="policy-h3">How to Exercise Your Rights</h3>
268
+ <h3 id="howtoexerciseyourrig" class="policy-h3">How to Exercise Your Rights</h3>
269
269
  <p>To submit a privacy inquiry, request data export, or request permanent deletion of your tenant domain space, please contact us using the information in Section 9 below. We will verify your identity (using your registered email or cryptographic keystone proof) and respond within the statutory timeframe (typically 45 days).</p>
270
270
  <hr class="divider">
271
- <h2 class="policy-h2">9. Contact Information &amp; Policy Updates</h2>
272
- <h3 class="policy-h3">Contact Us</h3>
271
+ <h2 id="9contactinformationp" class="policy-h2">9. Contact Information &amp; Policy Updates</h2>
272
+ <h3 id="contactus" class="policy-h3">Contact Us</h3>
273
273
  <p>If you have questions, comments, or requests regarding this Privacy Policy or our data handling practices, please reach out to us:</p>
274
274
  <ul>
275
275
  <li><strong>Open-Source Packages</strong>: Published on <strong>npm</strong> under the <code>@ibgib</code> scope.</li>
276
276
  <li><strong>Email / Privacy Inquiries</strong>: <code>ibgib.info@gmail.com</code></li>
277
277
  </ul>
278
- <h3 class="policy-h3">Updates to This Policy</h3>
278
+ <h3 id="updatestothispolicy" class="policy-h3">Updates to This Policy</h3>
279
279
  <p>We may update this Privacy Policy from time to time to reflect architectural advancements, legal requirements, or operational changes. When changes are made, the "Last Updated" date at the top of this document will be updated. We encourage you to review this policy periodically.</p>
280
280
  </main>
281
281
 
282
282
  <footer class="footer-bar">
283
283
  <span>© ibgib contributors</span>
284
- <span><a href="https://ibgib.space">ibgib.space</a> · <a href="https://github.com/ibgib" target="_blank" rel="noopener">GitHub</a></span>
284
+ <span><a href="https://ibgib.space">ibgib.space</a></span>
285
285
  </footer>
286
286
  </div>
287
287
  </body>
@@ -1 +1 @@
1
- import{p as e}from"./chunk-7YXHRAEW.mjs";import"./chunk-M2IO3EMM.mjs";console.log("space-gib early script executing...");e();
1
+ import{l as e}from"./chunk-O6EUMDNJ.mjs";import"./chunk-XZM4L3U6.mjs";console.log("space-gib early script executing...");e();
@@ -7171,9 +7171,11 @@ async function getDependencyGraph({ ibGib, ibGibs, ibGibAddr, ibGibAddrs, live,
7171
7171
  timeLogName,
7172
7172
  mapTjpAddrToLatestAddrsInSpace
7173
7173
  });
7174
- Object.values(graph).filter((ibGib2) => ibGib2.ib.startsWith("comment ")).forEach((ibGib2) => {
7175
- console.table(ibGib2);
7176
- });
7174
+ if (logalot11) {
7175
+ Object.values(graph).filter((ibGib2) => ibGib2.ib.startsWith("comment ")).forEach((ibGib2) => {
7176
+ console.table(ibGib2);
7177
+ });
7178
+ }
7177
7179
  if (logalot11) {
7178
7180
  console.log(`${lc2} graph size: ${Object.keys(graph).length} (I: c6cb5e7e1e2611d35b9006fac6503d22)`);
7179
7181
  const ibs = Object.values(graph).filter((ibGib2) => ibGib2.ib.startsWith("comment ") || ibGib2.ib.startsWith("pic ")).map((ibGib2) => ibGib2.ib);
@@ -21553,7 +21555,7 @@ var KeystoneService_V1 = class _KeystoneService_V1 {
21553
21555
  * from aggregated detail maps/arrays.
21554
21556
  */
21555
21557
  pruneTombstoneNulls(obj) {
21556
- if (!obj || typeof obj !== "object") {
21558
+ if (obj === null || obj === void 0 || typeof obj !== "object") {
21557
21559
  return obj;
21558
21560
  }
21559
21561
  if (Array.isArray(obj)) {
@@ -21562,7 +21564,7 @@ var KeystoneService_V1 = class _KeystoneService_V1 {
21562
21564
  for (const key of Object.keys(obj)) {
21563
21565
  if (obj[key] === null) {
21564
21566
  delete obj[key];
21565
- } else if (typeof obj[key] === "object") {
21567
+ } else if (obj[key] !== null && typeof obj[key] === "object") {
21566
21568
  this.pruneTombstoneNulls(obj[key]);
21567
21569
  }
21568
21570
  }
@@ -198,7 +198,7 @@ const fullHtml = `<!DOCTYPE html>
198
198
 
199
199
  <footer class="footer-bar">
200
200
  <span>© ibgib contributors</span>
201
- <span><a href="https://ibgib.space">ibgib.space</a> · <a href="https://github.com/ibgib" target="_blank" rel="noopener">GitHub</a></span>
201
+ <span><a href="https://ibgib.space">ibgib.space</a></span>
202
202
  </footer>
203
203
  </div>
204
204
  </body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibgib/space-gib",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "type": "module",
5
5
  "description": "ibgib storage and provider service — SaaS at ibgib.space",
6
6
  "scripts": {
@@ -12,11 +12,11 @@
12
12
  "build:test": "tsc -p tsconfig.test.json"
13
13
  },
14
14
  "dependencies": {
15
- "@ibgib/core-gib": "^0.1.77",
15
+ "@ibgib/core-gib": "^0.1.78",
16
16
  "@ibgib/helper-gib": "^0.0.37",
17
17
  "@ibgib/ts-gib": "^0.5.34",
18
- "@ibgib/web-gib": "^0.0.63",
19
- "@ibgib/node-gib": "^0.0.22"
18
+ "@ibgib/web-gib": "^0.0.64",
19
+ "@ibgib/node-gib": "^0.0.23"
20
20
  },
21
21
  "engines": {
22
22
  "node": ">=20.0.0"
@@ -8,4 +8,4 @@
8
8
  /**
9
9
  * Version of space-gib, auto-updated by the build process.
10
10
  */
11
- export const AUTO_GENERATED_VERSION = '0.0.21';
11
+ export const AUTO_GENERATED_VERSION = '0.0.22';
@@ -0,0 +1,330 @@
1
+ /**
2
+ * @module client/dev-tools/vcs-workspace
3
+ *
4
+ * Dev Tools panel button handlers for in-memory VCS Workspace Projection testing in space-gib.
5
+ * Utilizes the isomorphic VcsRepository facade and WebInMemoryWorkspaceProjectionSpace_V1.
6
+ */
7
+
8
+ import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
9
+ import { getGlobalMetaspace_waitIfNeeded } from '@ibgib/web-gib/dist/helpers.mjs';
10
+ import { WebInMemoryWorkspaceProjectionSpace_V1 } from '@ibgib/web-gib/dist/witness/space/web-in-memory-workspace-projection-space/web-in-memory-workspace-projection-space-v1.mjs';
11
+ import { InnerSpace_V1 } from '@ibgib/core-gib/dist/witness/space/inner-space/inner-space-v1.mjs';
12
+ import { DEFAULT_INNER_SPACE_DATA_V1 } from '@ibgib/core-gib/dist/witness/space/inner-space/inner-space-types.mjs';
13
+ import { getB2tFSBranchSpaceName } from '@ibgib/core-gib/dist/vcs/branch/branch-helper.mjs';
14
+ import { VcsRepository } from '@ibgib/core-gib/dist/vcs/vcs-repository.mjs';
15
+
16
+ import { devLog, lc } from './common.mjs';
17
+
18
+ interface VcsDevState {
19
+ backingSpace?: InnerSpace_V1;
20
+ wsSpace?: WebInMemoryWorkspaceProjectionSpace_V1;
21
+ repo?: VcsRepository;
22
+ }
23
+
24
+ export const vcsDevState: VcsDevState = {};
25
+ (window as any).vcsDevState = vcsDevState;
26
+
27
+ /**
28
+ * 1. Initialize in-memory branch CAS space, VcsRepository session, and seed sample files.
29
+ */
30
+ export function initVcsInitButton(): void {
31
+ const btn = document.getElementById('btn-vcs-init') as HTMLButtonElement | null;
32
+ if (!btn) { return; }
33
+
34
+ btn.addEventListener('click', async () => {
35
+ const lc_fn = `${lc}[btn-vcs-init]`;
36
+ try {
37
+ btn.disabled = true;
38
+ devLog('⏳ Initializing in-memory branch space & sample repo via VcsRepository...');
39
+
40
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
41
+
42
+ // 1. Create dedicated in-memory branch space
43
+ const branchSpaceName = getB2tFSBranchSpaceName('main');
44
+ const backingSpace = new InnerSpace_V1({
45
+ ...DEFAULT_INNER_SPACE_DATA_V1,
46
+ name: branchSpaceName,
47
+ spaceSubPath: branchSpaceName,
48
+ uuid: 'ws_backing_cas_space_uuid',
49
+ });
50
+ await backingSpace.initialized;
51
+ vcsDevState.backingSpace = backingSpace;
52
+
53
+ // Register backingSpace in metaspace local user spaces
54
+ try {
55
+ if ((metaspace as any).localUserSpaces && !(metaspace as any).localUserSpaces.includes(backingSpace)) {
56
+ (metaspace as any).localUserSpaces.push(backingSpace);
57
+ }
58
+ if ((metaspace as any).spaces && !(metaspace as any).spaces.includes(backingSpace)) {
59
+ (metaspace as any).spaces.push(backingSpace);
60
+ }
61
+ } catch {
62
+ // Ignore
63
+ }
64
+
65
+ // 2. Instantiate WebInMemoryWorkspaceProjectionSpace_V1
66
+ const wsSpace = new WebInMemoryWorkspaceProjectionSpace_V1({
67
+ initialData: {
68
+ name: 'web_ws_space_main',
69
+ uuid: 'web_ws_uuid',
70
+ workspaceRoot: '/',
71
+ vcsFolderName: '.vcsgib',
72
+ },
73
+ backingSpace,
74
+ });
75
+ await wsSpace.initialized;
76
+ vcsDevState.wsSpace = wsSpace;
77
+
78
+ // 3. Create VcsRepository session
79
+ const repo = new VcsRepository({
80
+ metaspace,
81
+ workspaceSpace: wsSpace,
82
+ localSpace: backingSpace,
83
+ activeBranchSpace: backingSpace,
84
+ enableBranchLocking: true,
85
+ });
86
+ vcsDevState.repo = repo;
87
+
88
+ // 4. Initialize repository
89
+ await repo.init({
90
+ rootFolderName: 'my-app',
91
+ defaultBranchName: 'main',
92
+ });
93
+
94
+ // 5. Seed initial files into virtual workspace
95
+ wsSpace.setVirtualFile('README.md', '# Space-Gib In-Memory Repo\n\nThis entire repository is projected in memory inside the browser.');
96
+ wsSpace.setVirtualFile('src/index.ts', 'export const app = "space-gib in-memory demo";\nconsole.log(app);');
97
+ wsSpace.setVirtualFile('src/helper.ts', 'export function add(a: number, b: number): number {\n return a + b;\n}');
98
+ wsSpace.setVirtualFile('.ibgibignore', 'node_modules/\n*.log\n');
99
+
100
+ // 6. Initial stage & commit
101
+ await repo.add([], { all: true });
102
+ const commitRes = await repo.commit({ message: 'Initial repository commit' });
103
+
104
+ devLog(`✅ In-Memory Repo initialized via VcsRepository!\n Commit: ${commitRes.commitAddr.slice(0, 8)}\n Files: ${wsSpace.listVirtualPaths().join(', ')}`);
105
+
106
+ // Enable action buttons
107
+ setBtnDisabled('btn-vcs-list', false);
108
+ setBtnDisabled('btn-vcs-status', false);
109
+ setBtnDisabled('btn-vcs-modify', false);
110
+ setBtnDisabled('btn-vcs-reset', false);
111
+ } catch (error) {
112
+ devLog(`❌ Init failed: ${extractErrorMsg(error)}`);
113
+ console.error(`${lc_fn}`, error);
114
+ } finally {
115
+ btn.disabled = true;
116
+ }
117
+ });
118
+ }
119
+
120
+ /**
121
+ * 2. List virtual files in in-memory projection space in a single formatted card.
122
+ */
123
+ export function initVcsListButton(): void {
124
+ const btn = document.getElementById('btn-vcs-list') as HTMLButtonElement | null;
125
+ if (!btn) { return; }
126
+
127
+ btn.addEventListener('click', () => {
128
+ try {
129
+ const wsSpace = vcsDevState.wsSpace;
130
+ if (!wsSpace) {
131
+ devLog('⚠️ Repo not initialized yet. Click (1) first.');
132
+ return;
133
+ }
134
+
135
+ const paths = wsSpace.listVirtualPaths();
136
+ const lines: string[] = [
137
+ `📁 --- IN-MEMORY VIRTUAL FILES (${paths.length} entries) ---`
138
+ ];
139
+
140
+ for (const p of paths) {
141
+ const text = wsSpace.getVirtualText(p);
142
+ const isDir = text === undefined || wsSpace.getVirtualFile(p)?.length === 0;
143
+ if (isDir) {
144
+ lines.push(` 📁 [DIR] ${p}`);
145
+ } else {
146
+ const preview = (text || '').replace(/\n/g, ' ').slice(0, 40);
147
+ lines.push(` 📄 [FILE] ${p.padEnd(22)} (${String(text?.length || 0).padStart(3)} chars) -> "${preview}..."`);
148
+ }
149
+ }
150
+
151
+ devLog(lines.join('\n'));
152
+ } catch (error) {
153
+ devLog(`❌ List failed: ${extractErrorMsg(error)}`);
154
+ }
155
+ });
156
+ }
157
+
158
+ /**
159
+ * 3. Inspect repository status via VcsRepository in a single formatted card.
160
+ */
161
+ export function initVcsStatusButton(): void {
162
+ const btn = document.getElementById('btn-vcs-status') as HTMLButtonElement | null;
163
+ if (!btn) { return; }
164
+
165
+ btn.addEventListener('click', async () => {
166
+ try {
167
+ const repo = vcsDevState.repo;
168
+ if (!repo) {
169
+ devLog('⚠️ Repo not initialized yet.');
170
+ return;
171
+ }
172
+
173
+ const status = await repo.status();
174
+ const lines: string[] = [
175
+ `📋 --- VCS STATUS (Branch: ${status.branchName}) ---`
176
+ ];
177
+
178
+ if (status.staged.length === 0 && status.modified.length === 0 && status.deleted.length === 0 && status.untracked.length === 0 && status.pendingComments.length === 0) {
179
+ lines.push(' ✨ Working tree clean (no changes)');
180
+ } else {
181
+ if (status.staged.length > 0) {
182
+ lines.push(` 🟢 Staged changes (${status.staged.length}):`);
183
+ for (const s of status.staged) { lines.push(` staged: ${s.path}`); }
184
+ }
185
+
186
+ if (status.modified.length > 0) {
187
+ lines.push(` 🟡 Changes not staged for commit (${status.modified.length}):`);
188
+ for (const m of status.modified) { lines.push(` modified: ${m.path}`); }
189
+ }
190
+
191
+ if (status.deleted.length > 0) {
192
+ lines.push(` 🔴 Deleted files (${status.deleted.length}):`);
193
+ for (const d of status.deleted) { lines.push(` deleted: ${d.path}`); }
194
+ }
195
+
196
+ if (status.untracked.length > 0) {
197
+ lines.push(` ⚪ Untracked files (${status.untracked.length}):`);
198
+ for (const u of status.untracked) { lines.push(` untracked: ${u.path}`); }
199
+ }
200
+
201
+ if (status.pendingComments.length > 0) {
202
+ lines.push(` 💬 Pending companion comments (${status.pendingComments.length}):`);
203
+ for (const c of status.pendingComments) { lines.push(` note for: ${c.targetRelPath} (${c.commentRelPath})`); }
204
+ }
205
+ }
206
+
207
+ devLog(lines.join('\n'));
208
+ } catch (error) {
209
+ devLog(`❌ Status check failed: ${extractErrorMsg(error)}`);
210
+ }
211
+ });
212
+ }
213
+
214
+ /**
215
+ * 4. Modify virtual file and add an untracked file directly in memory.
216
+ */
217
+ export function initVcsModifyButton(): void {
218
+ const btn = document.getElementById('btn-vcs-modify') as HTMLButtonElement | null;
219
+ if (!btn) { return; }
220
+
221
+ btn.addEventListener('click', () => {
222
+ try {
223
+ const wsSpace = vcsDevState.wsSpace;
224
+ if (!wsSpace) {
225
+ devLog('⚠️ Repo not initialized yet.');
226
+ return;
227
+ }
228
+
229
+ const lines: string[] = [
230
+ '✏️ Simulating user edits in in-browser editor...'
231
+ ];
232
+
233
+ // Modify existing file
234
+ const newContent = 'export const app = "space-gib (EDITED LIVE IN BROWSER!)";\nconsole.log(app);\nexport const timestamp = ' + Date.now() + ';';
235
+ wsSpace.setVirtualFile('src/index.ts', newContent);
236
+ lines.push(' ✏️ Updated "src/index.ts" with new code content.');
237
+
238
+ // Add an untracked file
239
+ wsSpace.setVirtualFile('src/new-component.ts', 'export const Component = () => "<div>New UI</div>";');
240
+ lines.push(' ➕ Created untracked file "src/new-component.ts".');
241
+
242
+ // Add a companion comment file
243
+ wsSpace.setVirtualFile('src/.ib.index.ts.md', '# Architectural Note on index.ts\nEdited live from Dev Tools!');
244
+ lines.push(' 💬 Added companion comment file "src/.ib.index.ts.md".');
245
+ lines.push('👉 Click (3) VCS Status to view detected changes, or (5) to commit!');
246
+
247
+ devLog(lines.join('\n'));
248
+ setBtnDisabled('btn-vcs-commit', false);
249
+ } catch (error) {
250
+ devLog(`❌ Modify failed: ${extractErrorMsg(error)}`);
251
+ }
252
+ });
253
+ }
254
+
255
+ /**
256
+ * 5. Stage and commit modified files using VcsRepository.
257
+ */
258
+ export function initVcsCommitButton(): void {
259
+ const btn = document.getElementById('btn-vcs-commit') as HTMLButtonElement | null;
260
+ if (!btn) { return; }
261
+
262
+ btn.addEventListener('click', async () => {
263
+ try {
264
+ btn.disabled = true;
265
+ const repo = vcsDevState.repo;
266
+ if (!repo) {
267
+ devLog('⚠️ Repo not initialized yet.');
268
+ return;
269
+ }
270
+
271
+ devLog('💾 Staging and committing changes via VcsRepository...');
272
+
273
+ // Stage all modified and new files
274
+ const addRes = await repo.add([], { all: true });
275
+
276
+ // Commit with message
277
+ const commitRes = await repo.commit({
278
+ message: 'Update index.ts and add new component with companion comment',
279
+ });
280
+
281
+ const lines: string[] = [
282
+ `🎉 Committed successfully via VcsRepository!`,
283
+ ` Commit: ${commitRes.commitAddr.slice(0, 8)}`,
284
+ ` Files Changed: ${commitRes.committedPaths.join(', ')}`,
285
+ ` Companion Comments Attached: ${commitRes.ingestedCommentsCount}`,
286
+ `👉 Click (3) VCS Status to verify clean working tree.`
287
+ ];
288
+
289
+ devLog(lines.join('\n'));
290
+ } catch (error) {
291
+ devLog(`❌ Commit failed: ${extractErrorMsg(error)}`);
292
+ console.error(`${lc}[btn-vcs-commit]`, error);
293
+ } finally {
294
+ btn.disabled = false;
295
+ }
296
+ });
297
+ }
298
+
299
+ /**
300
+ * 6. Discard working tree changes by restoring from snapshot via VcsRepository.
301
+ */
302
+ export function initVcsResetButton(): void {
303
+ const btn = document.getElementById('btn-vcs-reset') as HTMLButtonElement | null;
304
+ if (!btn) { return; }
305
+
306
+ btn.addEventListener('click', async () => {
307
+ try {
308
+ const { wsSpace, repo } = vcsDevState;
309
+ if (!wsSpace || !repo) {
310
+ devLog('⚠️ Repo not initialized yet.');
311
+ return;
312
+ }
313
+
314
+ devLog('🔄 Resetting virtual working tree from branch snapshot via VcsRepository...');
315
+ await repo.restore({ all: true });
316
+
317
+ // Keep .ibgibignore in place
318
+ wsSpace.setVirtualFile('.ibgibignore', 'node_modules/\n*.log\n');
319
+
320
+ devLog('✅ Working tree restored! All uncommitted edits discarded.\n👉 Click (3) VCS Status to confirm clean state.');
321
+ } catch (error) {
322
+ devLog(`❌ Reset failed: ${extractErrorMsg(error)}`);
323
+ }
324
+ });
325
+ }
326
+
327
+ function setBtnDisabled(id: string, disabled: boolean): void {
328
+ const el = document.getElementById(id) as HTMLButtonElement | null;
329
+ if (el) { el.disabled = disabled; }
330
+ }
@@ -25,8 +25,13 @@ import { init4_7bSetupButton, init4_7bSyncButton, init4_7bCheckButton } from './
25
25
  import { init4_8bSetupButton, init4_8bSyncButton, init4_8bCheckButton } from './dev-tools/phase-4-8.mjs';
26
26
  import { init4_9bSetupButton, init4_9bSyncButton, init4_9bCheckButton } from './dev-tools/phase-4-9.mjs';
27
27
  import { init4_10bSetupButton, init4_10bSyncButton, init4_10bCheckButton } from './dev-tools/phase-4-10.mjs';
28
+ import {
29
+ initVcsInitButton, initVcsListButton, initVcsStatusButton,
30
+ initVcsModifyButton, initVcsCommitButton, initVcsResetButton,
31
+ vcsDevState
32
+ } from './dev-tools/vcs-workspace.mjs';
28
33
 
29
- export { devLog, debugState };
34
+ export { devLog, debugState, vcsDevState };
30
35
 
31
36
  /**
32
37
  * Call once inside DOMContentLoaded to wire up all dev-tool buttons.
@@ -96,6 +101,13 @@ export function initDevTools(): void {
96
101
  init4_10bSetupButton();
97
102
  init4_10bSyncButton();
98
103
  init4_10bCheckButton();
104
+
105
+ initVcsInitButton();
106
+ initVcsListButton();
107
+ initVcsStatusButton();
108
+ initVcsModifyButton();
109
+ initVcsCommitButton();
110
+ initVcsResetButton();
99
111
  } catch (error) {
100
112
  console.error(`${lc_fn} ${extractErrorMsg(error)}`);
101
113
  }
@@ -123,6 +123,7 @@
123
123
  <option value="4.8B">Row 4.8B (Phase 4.8B)</option>
124
124
  <option value="4.9B">Row 4.9B (Phase 4.9B)</option>
125
125
  <option value="4.10B">Row 4.10B (Phase 4.10B)</option>
126
+ <option value="VCS">Row VCS (In-Memory Workspace)</option>
126
127
  </select>
127
128
  </div>
128
129
 
@@ -270,6 +271,19 @@
270
271
  </div>
271
272
  </div>
272
273
 
274
+ <!-- Row VCS: In-Memory Workspace Projection & VCS Engine -->
275
+ <div class="dev-panel-row-container" data-row-id="VCS">
276
+ <span class="dev-panel-row-label">VCS</span>
277
+ <div class="dev-panel-row">
278
+ <button id="btn-vcs-init" class="dev-btn">1. Init In-Memory Repo</button>
279
+ <button id="btn-vcs-list" class="dev-btn" disabled>2. List Virtual Files</button>
280
+ <button id="btn-vcs-status" class="dev-btn" disabled>3. VCS Status</button>
281
+ <button id="btn-vcs-modify" class="dev-btn" disabled>4. Edit app.ts</button>
282
+ <button id="btn-vcs-commit" class="dev-btn" disabled>5. Commit Edits</button>
283
+ <button id="btn-vcs-reset" class="dev-btn" disabled>6. Reset / Restore</button>
284
+ </div>
285
+ </div>
286
+
273
287
  <pre id="dev-panel-log" class="dev-panel-log" aria-live="polite" aria-label="Dev log"></pre>
274
288
  </section>
275
289
  </div>