@nossen/morphing 2.0.2 → 2.1.0

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.
package/dist/morph.d.ts CHANGED
@@ -94,6 +94,8 @@ export declare function unveil(m: morph): any;
94
94
  export type PorygonShard = {
95
95
  id: number;
96
96
  morph: morph;
97
+ layer?: PorygonLayer;
98
+ passport?: MorphPassport;
97
99
  };
98
100
  export type Porygon = {
99
101
  layoutId: number;
@@ -110,8 +112,71 @@ export declare function resolvePorygon(p: Porygon): any;
110
112
  /** Cube helpers for higher-level Freeland / RGBA tooling */
111
113
  export declare function cubeToRef(cube: MorphCube, space?: MorphSpace, localTag?: number): morph;
112
114
  export declare function refToCube(m: morph): MorphCube | undefined;
113
- export declare const MORPHING_VERSION = "0.1.6";
115
+ export declare const MORPHING_VERSION = "0.2.0";
114
116
  export declare function isMorph(x: any): x is morph;
115
117
  export declare function describeRefSpaces(): MorphRefSpaceDescription[];
116
118
  export declare function clearSpace(space: MorphSpace): void;
117
119
  export declare function clearAllSpaces(): void;
120
+ export type MorphOrigin = "internal" | "user_upload" | "decoded_payload" | "web" | "agent";
121
+ export type MorphTaint = "trusted" | "untrusted" | "quarantined" | "verified" | "rejected";
122
+ export type MorphActor = "system" | "agent" | "user" | "test";
123
+ export type MorphTrustEffect = "preserve" | "increase_after_validation" | "decrease" | "quarantine";
124
+ export type MorphLineageOp = "encode" | "decode" | "quantize" | "ref" | "porygon-shard" | "zen-wrap" | "verify" | (string & {});
125
+ export type MorphLineageStep = {
126
+ readonly op: MorphLineageOp;
127
+ readonly inputHash: string;
128
+ readonly outputHash: string;
129
+ readonly timestamp: string;
130
+ readonly actor: MorphActor;
131
+ readonly trustEffect: MorphTrustEffect;
132
+ };
133
+ export type MorphPermissions = {
134
+ readonly canRead: boolean;
135
+ readonly canDecode: boolean;
136
+ readonly canExecute: false;
137
+ readonly canBecomeConfig: boolean;
138
+ };
139
+ export type MorphRefScope = "process-local" | "serialized" | "external";
140
+ export type MorphPassport = {
141
+ readonly id: string;
142
+ readonly morph: morph;
143
+ readonly origin: MorphOrigin;
144
+ readonly taint: MorphTaint;
145
+ readonly lineage: readonly MorphLineageStep[];
146
+ readonly sourceHash?: string;
147
+ readonly payloadHash?: string;
148
+ readonly refScope?: MorphRefScope;
149
+ readonly permissions: MorphPermissions;
150
+ };
151
+ export type PorygonLayer = "technical" | "security" | "semantic" | "symbolic" | "spatial" | "provenance" | "render";
152
+ export type SerializedRefResult = {
153
+ readonly ok: true;
154
+ readonly namespace: string;
155
+ readonly index: number;
156
+ readonly handle: string;
157
+ } | {
158
+ readonly ok: false;
159
+ readonly error: "process-local-ref-not-serializable" | "not-a-ref";
160
+ };
161
+ export declare function morphHash(m: morph): string;
162
+ /** Enveloppe un morph interne (système, confiance initiale : trusted). */
163
+ export declare function wrapInternal(m: morph, sourceHash?: string): MorphPassport;
164
+ /** Enveloppe un morph externe (upload, payload, web…). Taint : untrusted par défaut. */
165
+ export declare function wrapExternal(m: morph, origin?: Exclude<MorphOrigin, "internal">, payloadHash?: string): MorphPassport;
166
+ /**
167
+ * Transforme un passport en propageant la lignée.
168
+ * Le taint ne peut jamais augmenter automatiquement — passe par verifyPassport.
169
+ */
170
+ export declare function transformPassport(input: MorphPassport, op: MorphLineageOp, outputMorph: morph, actor?: MorphActor, trustEffect?: MorphTrustEffect): MorphPassport;
171
+ /**
172
+ * Augmente la confiance après validation externe explicite.
173
+ * Ne fonctionne pas sur "rejected" ou "quarantined".
174
+ */
175
+ export declare function verifyPassport(passport: MorphPassport, verifiedBy?: MorphActor): MorphPassport;
176
+ /**
177
+ * Sérialisation de ref process-local.
178
+ * Une ref process-local ne peut PAS survivre à une sérialisation silencieuse.
179
+ * V1 : retourne toujours une erreur explicite — pas de manifest cross-process encore.
180
+ */
181
+ export declare function serializeRef(m: morph): SerializedRefResult;
182
+ export declare function isMorphPassport(x: unknown): x is MorphPassport;
package/dist/morph.js CHANGED
@@ -270,7 +270,7 @@ export function refToCube(m) {
270
270
  return undefined;
271
271
  }
272
272
  // --- Version ---
273
- export const MORPHING_VERSION = "0.1.6";
273
+ export const MORPHING_VERSION = "0.2.0";
274
274
  // --- Type guard ---
275
275
  export function isMorph(x) {
276
276
  return (x != null &&
@@ -312,3 +312,128 @@ export function clearAllSpaces() {
312
312
  MorphRefSpaces[i].length = 0;
313
313
  }
314
314
  }
315
+ // Identifiant stable d'un morph basé sur ses 4 bytes (hex).
316
+ export function morphHash(m) {
317
+ return (m.tt.toString(16).padStart(2, "0") +
318
+ m.d1.toString(16).padStart(2, "0") +
319
+ m.d2.toString(16).padStart(2, "0") +
320
+ m.d3.toString(16).padStart(2, "0"));
321
+ }
322
+ let _passportSeq = 0;
323
+ function newPassportId(m) {
324
+ return `mp-${morphHash(m)}-${(++_passportSeq).toString(36)}`;
325
+ }
326
+ function permissionsFor(taint) {
327
+ const open = taint === "trusted" || taint === "verified";
328
+ return {
329
+ canRead: taint !== "rejected",
330
+ canDecode: open,
331
+ canExecute: false,
332
+ canBecomeConfig: open,
333
+ };
334
+ }
335
+ function applyTrustEffect(current, effect, op) {
336
+ if (effect === "quarantine")
337
+ return "quarantined";
338
+ // decode depuis une source non-trusted → quarantaine automatique
339
+ if (op === "decode" && current !== "trusted" && current !== "verified")
340
+ return "quarantined";
341
+ if (effect === "decrease") {
342
+ return (current === "trusted" || current === "verified") ? "untrusted" : current;
343
+ }
344
+ // "increase_after_validation" et "preserve" ne changent rien ici —
345
+ // l'augmentation de confiance passe uniquement par verifyPassport.
346
+ return current;
347
+ }
348
+ /** Enveloppe un morph interne (système, confiance initiale : trusted). */
349
+ export function wrapInternal(m, sourceHash) {
350
+ return {
351
+ id: newPassportId(m),
352
+ morph: m,
353
+ origin: "internal",
354
+ taint: "trusted",
355
+ lineage: [],
356
+ sourceHash,
357
+ refScope: kindOf(m) === MorphKind.Ref ? "process-local" : undefined,
358
+ permissions: permissionsFor("trusted"),
359
+ };
360
+ }
361
+ /** Enveloppe un morph externe (upload, payload, web…). Taint : untrusted par défaut. */
362
+ export function wrapExternal(m, origin = "decoded_payload", payloadHash) {
363
+ return {
364
+ id: newPassportId(m),
365
+ morph: m,
366
+ origin,
367
+ taint: "untrusted",
368
+ lineage: [],
369
+ payloadHash,
370
+ refScope: kindOf(m) === MorphKind.Ref ? "external" : undefined,
371
+ permissions: permissionsFor("untrusted"),
372
+ };
373
+ }
374
+ /**
375
+ * Transforme un passport en propageant la lignée.
376
+ * Le taint ne peut jamais augmenter automatiquement — passe par verifyPassport.
377
+ */
378
+ export function transformPassport(input, op, outputMorph, actor = "system", trustEffect = "preserve") {
379
+ const step = {
380
+ op,
381
+ inputHash: morphHash(input.morph),
382
+ outputHash: morphHash(outputMorph),
383
+ timestamp: new Date().toISOString(),
384
+ actor,
385
+ trustEffect,
386
+ };
387
+ const newTaint = applyTrustEffect(input.taint, trustEffect, op);
388
+ return {
389
+ id: newPassportId(outputMorph),
390
+ morph: outputMorph,
391
+ origin: input.origin,
392
+ taint: newTaint,
393
+ lineage: [...input.lineage, step],
394
+ sourceHash: input.sourceHash,
395
+ payloadHash: input.payloadHash,
396
+ refScope: kindOf(outputMorph) === MorphKind.Ref ? (input.refScope ?? "process-local") : undefined,
397
+ permissions: permissionsFor(newTaint),
398
+ };
399
+ }
400
+ /**
401
+ * Augmente la confiance après validation externe explicite.
402
+ * Ne fonctionne pas sur "rejected" ou "quarantined".
403
+ */
404
+ export function verifyPassport(passport, verifiedBy = "system") {
405
+ if (passport.taint === "rejected" || passport.taint === "quarantined")
406
+ return passport;
407
+ const step = {
408
+ op: "verify",
409
+ inputHash: morphHash(passport.morph),
410
+ outputHash: morphHash(passport.morph),
411
+ timestamp: new Date().toISOString(),
412
+ actor: verifiedBy,
413
+ trustEffect: "increase_after_validation",
414
+ };
415
+ return {
416
+ ...passport,
417
+ taint: "verified",
418
+ lineage: [...passport.lineage, step],
419
+ permissions: permissionsFor("verified"),
420
+ };
421
+ }
422
+ /**
423
+ * Sérialisation de ref process-local.
424
+ * Une ref process-local ne peut PAS survivre à une sérialisation silencieuse.
425
+ * V1 : retourne toujours une erreur explicite — pas de manifest cross-process encore.
426
+ */
427
+ export function serializeRef(m) {
428
+ if (kindOf(m) !== MorphKind.Ref)
429
+ return { ok: false, error: "not-a-ref" };
430
+ // ref process-local → erreur explicite, jamais silencieuse
431
+ return { ok: false, error: "process-local-ref-not-serializable" };
432
+ }
433
+ export function isMorphPassport(x) {
434
+ return (x != null &&
435
+ typeof x === "object" &&
436
+ "morph" in x && isMorph(x.morph) &&
437
+ "taint" in x && typeof x.taint === "string" &&
438
+ "lineage" in x && Array.isArray(x.lineage));
439
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nossen/morphing",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "Compact 4-byte value shapes and RGBA/cube helpers for low-friction transport.",
5
5
  "author": "NOSSEN <contact@funesterie.me>",
6
6
  "license": "MIT",
@@ -21,7 +21,8 @@
21
21
  "exports": {
22
22
  ".": {
23
23
  "import": "./dist/morph.js",
24
- "types": "./dist/morph.d.ts"
24
+ "types": "./dist/morph.d.ts",
25
+ "default": "./dist/morph.js"
25
26
  },
26
27
  "./package.json": "./package.json"
27
28
  },