@majikah/majik-slink 0.1.0 → 0.2.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/README.md +84 -51
- package/dist/core/types.d.ts +3 -2
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -3,21 +3,24 @@
|
|
|
3
3
|
[](https://www.thezelijah.world) 
|
|
4
4
|
  [](https://opensource.org/licenses/Apache-2.0) 
|
|
5
5
|
|
|
6
|
-
**MajikSLink** is a specialized TypeScript library designed for URL ownership
|
|
6
|
+
**MajikSLink** is a specialized TypeScript library designed for URL binding, ownership, and cryptographic attribution. It provides a robust, zero-trust mechanism to prove that a specific digital identity (via a **MajikKey** and **MUID**) controls or is attested to a publicly accessible web resource (such as a YouTube channel, social media profile, DNS record, or personal blog).
|
|
7
7
|
|
|
8
|
-
By combining traditional **Ed25519** signatures with post-quantum **ML-DSA-87 (Dilithium)** hybrid cryptography via `@majikah/majik-signature`, MajikSLink ensures that your identity-to-URL associations are tamper-proof
|
|
8
|
+
By combining traditional **Ed25519** signatures with post-quantum **ML-DSA-87 (Dilithium)** hybrid cryptography via `@majikah/majik-signature`, MajikSLink ensures that your identity-to-URL associations are tamper-proof, resilient against future quantum threats, and structurally decoupled for decentralized verification.
|
|
9
9
|
|
|
10
|
-
Identities can be created and managed via the web application at **[https://id.majikah.solutions](https://id.majikah.solutions)
|
|
10
|
+
Identities can be created and managed via the web application at **[https://id.majikah.solutions](https://id.majikah.solutions)**.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
## Key Features
|
|
15
15
|
|
|
16
|
-
1. **Deterministic URL Normalization:** Automatically converts URLs into a canonical
|
|
17
|
-
2. **
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
1. **Deterministic URL Normalization:** Automatically converts URLs into a canonical format (`majik-slink-v1:<subdomain>::<sld>::<tld>::<path>`). It strips tracking queries, fragments, and trailing slashes so the exact same core resource always generates a consistent hash and verification code.
|
|
17
|
+
2. **Flexible Claim Types:**
|
|
18
|
+
* **`ownership`**: The strongest claim, indicating domain control. Verified via DNS TXT records.
|
|
19
|
+
* **`attribution`**: Indicates content control (e.g., a channel bio or GitHub README) but not DNS control. Verified via page content scraping.
|
|
20
|
+
* **`reference`**: A pure cryptographic attestation ("this URL is relevant to me") with no independent third-party verification possible.
|
|
21
|
+
3. **Compact Post-Quantum Signatures:** Signatures are stored in a compact envelope. Public keys are *never* embedded directly, requiring verifiers to externally resolve them via the signer's `muid`, ensuring up-to-date registry checks.
|
|
22
|
+
4. **Challenge-Response Verification:** Derives a short OTP-style code (`vCode`) from the SHA-256 hash of the canonical URL to be placed in DNS TXT records or page bios.
|
|
23
|
+
5. **Serialization Ready:** Built-in support for flawless JSON rehydration (`toJSON` / `fromJSON`) and Base64 serialization (`serialize` / `deserialize`).
|
|
21
24
|
|
|
22
25
|
---
|
|
23
26
|
|
|
@@ -27,82 +30,113 @@ Identities can be created and managed via the web application at **[https://id.m
|
|
|
27
30
|
npm install @majikah/majik-slink @majikah/majik-key @majikah/majik-signature
|
|
28
31
|
```
|
|
29
32
|
|
|
33
|
+
---
|
|
34
|
+
|
|
30
35
|
## Quick Start & Usage
|
|
31
36
|
|
|
32
|
-
### 1.
|
|
33
|
-
|
|
37
|
+
### 1. Generating a UI Challenge (Without Signing)
|
|
38
|
+
If you are building a UI and want to show the user their verification code *before* they confirm and sign, you can generate a challenge using just the URL.
|
|
34
39
|
|
|
35
40
|
```typescript
|
|
36
41
|
import { MajikSLink } from "@majikah/majik-slink";
|
|
42
|
+
|
|
43
|
+
const preview = await MajikSLink.generateChallenge("https://github.com/majikah/repo?utm_source=test#readme");
|
|
44
|
+
|
|
45
|
+
if (preview) {
|
|
46
|
+
console.log("Canonical URL:", preview.cleanUrl); // https://github.com/majikah/repo
|
|
47
|
+
console.log("Ask user to add this to their bio:", preview.v_code); // majik-slink:xxxx...
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Creating and Signing a New SLink
|
|
52
|
+
To permanently link an identity to a URL, create a `MajikSLink` instance using an unlocked `MajikKey`.
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
37
55
|
import { MajikKey } from "@majikah/majik-key";
|
|
38
56
|
|
|
39
|
-
// 1. Initialize your identity
|
|
40
|
-
const
|
|
57
|
+
// 1. Initialize and unlock your identity
|
|
58
|
+
const mnemonic = MajikKey.generateMnemonic();
|
|
59
|
+
const key = await MajikKey.create(mnemonic, 'my-passphrase', 'My Signing Key');
|
|
41
60
|
const userId = "user_abc123";
|
|
42
61
|
const muid = "muid_xyz987";
|
|
43
62
|
|
|
44
63
|
// 2. Create the SLink payload
|
|
45
|
-
const targetUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
64
|
+
const targetUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";
|
|
65
|
+
|
|
46
66
|
const slink = await MajikSLink.create(targetUrl, key, userId, muid, {
|
|
47
|
-
claimType: "
|
|
67
|
+
claimType: "attribution" // Automatically defaults verificationMethod to "page_content"
|
|
48
68
|
});
|
|
49
69
|
|
|
50
|
-
console.log("
|
|
51
|
-
console.log("
|
|
70
|
+
console.log("Status:", slink.status); // "unverified"
|
|
71
|
+
console.log("Source Platform:", slink.source); // "youtube"
|
|
52
72
|
```
|
|
53
73
|
|
|
54
|
-
###
|
|
55
|
-
|
|
74
|
+
### 3. Displaying Verification Requirements
|
|
75
|
+
Depending on the `claimType`, you can guide users on how to prove their link:
|
|
56
76
|
|
|
57
77
|
```typescript
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
console.log("
|
|
62
|
-
|
|
78
|
+
if (slink.verificationMethod === "dns_txt") {
|
|
79
|
+
console.log("Add a TXT Record:");
|
|
80
|
+
console.log("Name:", slink.dnsRecordName); // _majik-challenge.youtube.com
|
|
81
|
+
console.log("Value:", slink.dnsRecordValue); // majik-slink-verify=majik-slink:a1b2...
|
|
82
|
+
} else if (slink.verificationMethod === "page_content") {
|
|
83
|
+
console.log("Add this code anywhere in your bio or README:");
|
|
84
|
+
console.log(slink.vCode); // majik-slink:a1b2...
|
|
85
|
+
|
|
86
|
+
// You can also display it in nice OTP chunks:
|
|
87
|
+
console.log("Display Code:", slink.codeChunks.join("-"));
|
|
63
88
|
}
|
|
64
89
|
```
|
|
65
90
|
|
|
66
|
-
### 3. DNS TXT Verification Formatting
|
|
67
|
-
For domain ownership claims, `MajikSLink` automatically formats the required DNS properties.
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
console.log("DNS Record Name:", slink.dnsRecordName); // e.g., _majik-challenge.github.com
|
|
71
|
-
console.log("DNS Record Value:", slink.dnsRecordValue); // e.g., majik-slink-verify=majik-slink:...
|
|
72
|
-
```
|
|
73
|
-
|
|
74
91
|
### 4. Verifying Cryptographic Signatures
|
|
75
|
-
|
|
92
|
+
Because MajikSLink uses **compact signatures**, public keys are not stored in the SLink payload. You must fetch the public keys (via `muid`) from your trusted identity registry to verify the claim.
|
|
76
93
|
|
|
77
94
|
```typescript
|
|
78
95
|
import { MajikSignature } from "@majikah/majik-signature";
|
|
79
96
|
|
|
80
|
-
//
|
|
81
|
-
const publicKeys =
|
|
82
|
-
ed25519: "base64-ed25519-pubkey",
|
|
83
|
-
mldsa: "base64-mldsa-pubkey"
|
|
84
|
-
};
|
|
97
|
+
// 1. Fetch public keys from your trusted registry using the SLink's MUID
|
|
98
|
+
const publicKeys = await fetchPublicKeysForMuid(slink.muid);
|
|
85
99
|
|
|
86
|
-
// Verify the
|
|
100
|
+
// 2. Verify the cryptographic signature against the canonical URL
|
|
87
101
|
const verificationResult = slink.verify(publicKeys);
|
|
88
102
|
|
|
89
103
|
if (verificationResult.valid) {
|
|
90
104
|
console.log("Valid signature from:", verificationResult.signerId);
|
|
91
|
-
|
|
105
|
+
|
|
106
|
+
// 3. (Optional) If you also successfully scraped the vCode from the web:
|
|
107
|
+
slink.markVerified();
|
|
92
108
|
} else {
|
|
93
109
|
slink.markSignatureInvalid();
|
|
94
110
|
}
|
|
95
111
|
```
|
|
96
112
|
|
|
97
|
-
|
|
98
|
-
|
|
113
|
+
*Note: You can also verify statically without hydrating via `MajikSLink.verifySignature(slinkJSON, publicKeys)`.*
|
|
114
|
+
|
|
115
|
+
### 5. Utilities & Comparisons
|
|
116
|
+
Easily compare URLs to see if they resolve to the exact same signed resource:
|
|
99
117
|
|
|
100
118
|
```typescript
|
|
101
|
-
//
|
|
119
|
+
// Ignores query params and fragments automatically
|
|
120
|
+
const isMatch = slink.isSameResource("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=42s");
|
|
121
|
+
console.log(isMatch); // true
|
|
122
|
+
|
|
123
|
+
// View a human-readable debug summary
|
|
124
|
+
console.log(slink.toSummary());
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 6. Serialization and Database Storage
|
|
128
|
+
Store and retrieve `MajikSLink` objects seamlessly.
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// Export to JSON for Database storage
|
|
102
132
|
const jsonPayload = slink.toJSON();
|
|
103
133
|
|
|
104
|
-
// Hydrate from DB
|
|
134
|
+
// Hydrate from DB (Note: signatures must still be verified with external keys)
|
|
105
135
|
const hydratedSLink = MajikSLink.fromJSON(jsonPayload);
|
|
136
|
+
|
|
137
|
+
// Export to Base64 (Useful for QR codes or URL parameters)
|
|
138
|
+
const base64String = slink.serialize();
|
|
139
|
+
const fromBase64 = MajikSLink.deserialize(base64String);
|
|
106
140
|
```
|
|
107
141
|
|
|
108
142
|
---
|
|
@@ -125,17 +159,16 @@ const hydratedSLink = MajikSLink.fromJSON(jsonPayload);
|
|
|
125
159
|
|
|
126
160
|
## Author
|
|
127
161
|
|
|
128
|
-
|
|
162
|
+
Developed by **Josef Elijah Fabian (Zelijah)** | [Majikah Solutions OPC](https://majikah.solutions/about)
|
|
129
163
|
|
|
130
|
-
**Developer**: Josef Elijah
|
|
131
|
-
**
|
|
132
|
-
**
|
|
133
|
-
**Project Repository**: [https://github.com/Majikah/majik-slink](https://github.com/Majikah/majik-slink)
|
|
164
|
+
**Developer**: [Josef Elijah Fabian](https://github.com/jedlsf)
|
|
165
|
+
**GitHub**: [https://github.com/Majikah](https://github.com/Majikah)
|
|
166
|
+
**Project Repository**: [https://github.com/Majikah/majik-slink](https://github.com/Majikah/majik-slink)
|
|
134
167
|
|
|
135
168
|
---
|
|
136
169
|
|
|
137
170
|
## Contact
|
|
138
171
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
172
|
+
- **Business Email**: [business@majikah.solutions](mailto:business@majikah.solutions)
|
|
173
|
+
- **Official Website**: [https://www.thezelijah.world](https://www.thezelijah.world)
|
|
174
|
+
- **Majikah Ecosystem**: [https://majikah.solutions](https://majikah.solutions)
|
package/dist/core/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ISODateString } from "@majikah/majik-key";
|
|
1
2
|
import { MajikSignatureCompactJSON } from "@majikah/majik-signature";
|
|
2
3
|
/**
|
|
3
4
|
* What kind of relationship the user claims to have with this URL.
|
|
@@ -41,9 +42,9 @@ export interface MajikSLinkJSON {
|
|
|
41
42
|
/** Verification status */
|
|
42
43
|
status: SLinkVerificationStatus;
|
|
43
44
|
/** ISO timestamp of when this SLink was created */
|
|
44
|
-
timestamp:
|
|
45
|
+
timestamp: ISODateString;
|
|
45
46
|
/** ISO timestamp of the last verification attempt, or null */
|
|
46
|
-
verified_at:
|
|
47
|
+
verified_at: ISODateString | null;
|
|
47
48
|
/** Compact envelope — no embedded public keys. Resolve via muid/signerId at verify time. */
|
|
48
49
|
signature: MajikSignatureCompactJSON;
|
|
49
50
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@majikah/majik-slink",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "Majik SLink is a specialized TypeScript library designed for URL ownership verification and cryptographic identity linking. It provides a robust mechanism to prove that a specific digital identity (a MajikKey) controls a publicly accessible web resource (such as a YouTube channel, social media profile, or personal blog).",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.2.0",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "Zelijah",
|
|
8
8
|
"main": "./dist/index.js",
|
|
@@ -50,13 +50,13 @@
|
|
|
50
50
|
"update": "npm i @majikah/majik-key@latest @majikah/majik-signature@latest"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@majikah/majik-key": "^0.
|
|
54
|
-
"@majikah/majik-signature": "^0.
|
|
53
|
+
"@majikah/majik-key": "^0.4.0",
|
|
54
|
+
"@majikah/majik-signature": "^0.3.0",
|
|
55
55
|
"@types/psl": "^1.1.3",
|
|
56
56
|
"psl": "^1.15.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@types/node": "^26.
|
|
59
|
+
"@types/node": "^26.2.0",
|
|
60
60
|
"vitest": "^4.1.10"
|
|
61
61
|
}
|
|
62
62
|
}
|