javascript-solid-server 0.0.86 → 0.0.87

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.
@@ -324,7 +324,8 @@
324
324
  "Bash(npm link)",
325
325
  "Bash(npm link:*)",
326
326
  "Bash(git push)",
327
- "Bash(ulimit:*)"
327
+ "Bash(ulimit:*)",
328
+ "Bash(gh label:*)"
328
329
  ]
329
330
  }
330
331
  }
package/README.md CHANGED
@@ -6,8 +6,11 @@ A minimal, fast, JSON-LD native Solid server.
6
6
 
7
7
  ## Features
8
8
 
9
- ### Implemented (v0.0.79)
9
+ ### Implemented (v0.0.86)
10
10
 
11
+ - **Live Reload** - Auto-refresh browser on file changes (`--live-reload`)
12
+ - **Read-Only Mode** - Disable write operations for static hosting (`--read-only`)
13
+ - **Public Mode** - Skip WAC for open read/write access (`--public`)
11
14
  - **Schnorr SSO** - Passwordless login via BIP-340 Schnorr signatures using NIP-07 browser extensions (Podkey, nos2x, Alby)
12
15
  - **Passkey Authentication** - WebAuthn/FIDO2 passwordless login with Touch ID, Face ID, or security keys
13
16
  - **HTTP Range Requests** - Partial content delivery for large files and media streaming
@@ -35,7 +38,7 @@ A minimal, fast, JSON-LD native Solid server.
35
38
  - **Content Negotiation** - Turtle <-> JSON-LD conversion, including HTML data islands
36
39
  - **CORS Support** - Full cross-origin resource sharing
37
40
  - **Git HTTP Backend** - Clone and push to containers via `git` protocol
38
- - **Nostr Relay** - Integrated NIP-01 relay on the same port (`wss://your.pod/relay`)
41
+ - **Nostr Relay** - Integrated NIP-01/NIP-11/NIP-16 relay on the same port (`wss://your.pod/relay`)
39
42
  - **Invite-Only Registration** - CLI-managed invite codes for controlled signups
40
43
  - **Storage Quotas** - Per-user storage limits with CLI management
41
44
  - **Security** - Blocks access to dotfiles (`.git/`, `.env`, etc.) except Solid-specific ones
@@ -139,6 +142,9 @@ jss --help # Show help
139
142
  | `--ap-display-name <name>` | ActivityPub display name | (username) |
140
143
  | `--ap-summary <text>` | ActivityPub bio/summary | - |
141
144
  | `--ap-nostr-pubkey <hex>` | Nostr pubkey for identity linking | - |
145
+ | `--public` | Allow unauthenticated access (skip WAC) | false |
146
+ | `--read-only` | Disable PUT/DELETE/PATCH methods | false |
147
+ | `--live-reload` | Auto-refresh browser on file changes | false |
142
148
  | `-q, --quiet` | Suppress logs | false |
143
149
 
144
150
  ### Environment Variables
@@ -159,6 +165,10 @@ export JSS_WEBID_TLS=true
159
165
  export JSS_DEFAULT_QUOTA=100MB
160
166
  export JSS_ACTIVITYPUB=true
161
167
  export JSS_AP_USERNAME=alice
168
+ export JSS_PUBLIC=true
169
+ export JSS_READ_ONLY=true
170
+ export JSS_LIVE_RELOAD=true
171
+ export JSS_SOLIDOS_UI=true
162
172
  jss start
163
173
  ```
164
174
 
@@ -868,7 +878,7 @@ curl -X POST https://example.com/.pods \
868
878
 
869
879
  | Server | Size | Deps | Notes |
870
880
  |--------|------|------|-------|
871
- | [JSS](https://github.com/JavaScriptSolidServer/JavaScriptSolidServer) | 432 KB | 10 | Minimal, JSON-LD native |
881
+ | [JSS](https://github.com/JavaScriptSolidServer/JavaScriptSolidServer) | ~14K LoC | 14 | Minimal, JSON-LD native |
872
882
  | [NSS](https://github.com/nodeSolidServer/node-solid-server) | 777 KB | 58 | Original Solid server |
873
883
  | [CSS](https://github.com/CommunitySolidServer/CommunitySolidServer) | 5.8 MB | 70 | Modular, configurable |
874
884
  | [Pivot](https://github.com/solid-contrib/pivot) | ~6 MB | 70+ | Built on CSS |
@@ -941,7 +951,7 @@ npm run benchmark
941
951
  npm test
942
952
  ```
943
953
 
944
- Currently passing: **223 tests** (including 27 conformance tests)
954
+ Currently passing: **229 tests** (including 27 conformance tests)
945
955
 
946
956
  ### Conformance Test Harness (CTH)
947
957
 
@@ -988,12 +998,12 @@ src/
988
998
  │ ├── filesystem.js # File operations
989
999
  │ └── quota.js # Storage quota management
990
1000
  ├── auth/
991
- │ ├── middleware.js # Auth hook
992
- │ ├── token.js # Simple token auth
993
- │ ├── solid-oidc.js # DPoP verification
994
- │ ├── nostr.js # NIP-98 Nostr authentication
995
- │ ├── did-nostr.js # did:nostr → WebID resolution
996
- │ └── webid-tls.js # WebID-TLS client certificate auth
1001
+ │ ├── middleware.js # Auth hook
1002
+ │ ├── token.js # Simple token auth
1003
+ │ ├── solid-oidc.js # DPoP verification
1004
+ │ ├── nostr.js # NIP-98 Nostr authentication
1005
+ │ ├── did-nostr.js # did:nostr → WebID resolution
1006
+ │ └── webid-tls.js # WebID-TLS client certificate auth
997
1007
  ├── wac/
998
1008
  │ ├── parser.js # ACL parsing
999
1009
  │ └── checker.js # Permission checking
@@ -1010,14 +1020,16 @@ src/
1010
1020
  │ ├── events.js # Event emitter
1011
1021
  │ └── websocket.js # solid-0.1 protocol
1012
1022
  ├── idp/
1013
- │ ├── index.js # Identity Provider plugin
1014
- │ ├── provider.js # oidc-provider config
1015
- │ ├── adapter.js # Filesystem adapter
1016
- │ ├── accounts.js # User account management
1017
- │ ├── keys.js # JWKS key management
1018
- │ ├── interactions.js # Login/consent handlers
1019
- │ ├── views.js # HTML templates
1020
- └── invites.js # Invite code management
1023
+ │ ├── index.js # Identity Provider plugin
1024
+ │ ├── provider.js # oidc-provider config
1025
+ │ ├── adapter.js # Filesystem adapter
1026
+ │ ├── accounts.js # User account management
1027
+ │ ├── credentials.js # Credentials endpoint
1028
+ │ ├── keys.js # JWKS key management
1029
+ │ ├── interactions.js # Login/consent handlers
1030
+ ├── passkey.js # WebAuthn/FIDO2 passkey support
1031
+ │ ├── views.js # HTML templates
1032
+ │ └── invites.js # Invite code management
1021
1033
  ├── ap/
1022
1034
  │ ├── index.js # ActivityPub plugin
1023
1035
  │ ├── keys.js # RSA keypair management
@@ -1030,23 +1042,31 @@ src/
1030
1042
  ├── rdf/
1031
1043
  │ ├── turtle.js # Turtle <-> JSON-LD
1032
1044
  │ └── conneg.js # Content negotiation
1045
+ ├── mashlib/
1046
+ │ └── index.js # Mashlib data browser plugin
1033
1047
  └── utils/
1034
- ├── url.js # URL utilities
1035
- └── conditional.js # If-Match/If-None-Match
1048
+ ├── url.js # URL utilities
1049
+ ├── conditional.js # If-Match/If-None-Match
1050
+ └── ssrf.js # SSRF protection
1036
1051
  ```
1037
1052
 
1038
1053
  ## Dependencies
1039
1054
 
1040
- Minimal dependencies for a fast, secure server:
1055
+ 14 direct dependencies for a fast, secure server:
1041
1056
 
1042
1057
  - **fastify** - High-performance HTTP server
1058
+ - **@fastify/middie** - Express/Connect middleware bridge (for IdP)
1059
+ - **@fastify/rate-limit** - Rate limiting for API endpoints
1043
1060
  - **@fastify/websocket** - WebSocket support for notifications
1061
+ - **@simplewebauthn/server** - Passkey/WebAuthn authentication
1062
+ - **bcryptjs** - Password hashing (pure JS, works on Termux/Android)
1063
+ - **commander** - CLI command parsing
1044
1064
  - **fs-extra** - Enhanced file operations
1045
1065
  - **jose** - JWT/JWK handling for Solid-OIDC
1066
+ - **microfed** - ActivityPub primitives (only when activitypub enabled)
1046
1067
  - **n3** - Turtle parsing (only used when conneg enabled)
1068
+ - **nostr-tools** - Nostr protocol and Schnorr signature verification
1047
1069
  - **oidc-provider** - OpenID Connect Identity Provider (only when IdP enabled)
1048
- - **bcryptjs** - Password hashing (only when IdP enabled)
1049
- - **microfed** - ActivityPub primitives (only when activitypub enabled)
1050
1070
  - **sql.js** - SQLite storage for federation data (WASM, cross-platform)
1051
1071
 
1052
1072
  ## License
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "javascript-solid-server",
3
- "version": "0.0.86",
3
+ "version": "0.0.87",
4
4
  "description": "A minimal, fast Solid server",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/config.js CHANGED
@@ -228,6 +228,11 @@ export async function loadConfig(cliOptions = {}, configFile = null) {
228
228
  config.logger = false;
229
229
  }
230
230
 
231
+ // Mashlib requires content negotiation for Turtle support
232
+ if (config.mashlib || config.mashlibCdn) {
233
+ config.conneg = true;
234
+ }
235
+
231
236
  // Validate SSL config
232
237
  if ((config.sslKey && !config.sslCert) || (!config.sslKey && config.sslCert)) {
233
238
  throw new Error('Both --ssl-key and --ssl-cert must be provided together');
package/src/wac/parser.js CHANGED
@@ -144,8 +144,9 @@ function parseAuthorization(node, aclUrl) {
144
144
  auth.default = parseUriArray(node['acl:default'] || node['default'])
145
145
  .map(uri => resolveUri(uri, baseUrl));
146
146
 
147
- // Parse agents (WebIDs can be relative too)
148
- auth.agents = parseUriArray(node['acl:agent'] || node['agent']);
147
+ // Parse agents (WebIDs can be relative too) - resolve against ACL URL
148
+ auth.agents = parseUriArray(node['acl:agent'] || node['agent'])
149
+ .map(uri => resolveUri(uri, aclUrl));
149
150
 
150
151
  // Parse agentClass
151
152
  auth.agentClasses = parseUriArray(node['acl:agentClass'] || node['agentClass']);
package/test/wac.test.js CHANGED
@@ -187,6 +187,23 @@ describe('WAC Parser', () => {
187
187
  `Expected accessTo to include 'https://alice.example/other/', got: ${auths[0].accessTo}`);
188
188
  });
189
189
 
190
+ it('should resolve relative agent URIs against ACL URL', async () => {
191
+ const acl = {
192
+ '@context': { 'acl': 'http://www.w3.org/ns/auth/acl#' },
193
+ '@id': '#owner',
194
+ '@type': 'acl:Authorization',
195
+ 'acl:agent': { '@id': './#me' },
196
+ 'acl:accessTo': { '@id': './' },
197
+ 'acl:mode': [{ '@id': 'acl:Read' }]
198
+ };
199
+
200
+ const auths = await parseAcl(JSON.stringify(acl), 'https://alice.example/.acl');
201
+
202
+ assert.strictEqual(auths.length, 1);
203
+ assert.ok(auths[0].agents.includes('https://alice.example/#me'),
204
+ `Expected agents to include 'https://alice.example/#me', got: ${auths[0].agents}`);
205
+ });
206
+
190
207
  it('should keep absolute URLs unchanged', async () => {
191
208
  const acl = {
192
209
  '@context': { 'acl': 'http://www.w3.org/ns/auth/acl#' },
@@ -1,120 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>fonstr - Your Nostr Relay</title>
7
- <style>
8
- * { margin: 0; padding: 0; box-sizing: border-box; }
9
- body {
10
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
11
- background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
12
- color: white;
13
- min-height: 100vh;
14
- display: flex;
15
- align-items: center;
16
- justify-content: center;
17
- padding: 2rem;
18
- }
19
- .container {
20
- text-align: center;
21
- max-width: 600px;
22
- }
23
- h1 {
24
- font-size: 3rem;
25
- margin-bottom: 0.5rem;
26
- }
27
- .emoji {
28
- font-size: 4rem;
29
- margin-bottom: 1rem;
30
- }
31
- p {
32
- font-size: 1.25rem;
33
- opacity: 0.95;
34
- margin-bottom: 2rem;
35
- line-height: 1.6;
36
- }
37
- .relay-info {
38
- background: rgba(255, 255, 255, 0.2);
39
- backdrop-filter: blur(10px);
40
- border-radius: 1rem;
41
- padding: 2rem;
42
- margin: 2rem 0;
43
- }
44
- code {
45
- background: rgba(255, 255, 255, 0.3);
46
- padding: 0.5rem 1rem;
47
- border-radius: 0.5rem;
48
- font-size: 1.1rem;
49
- display: inline-block;
50
- margin: 0.5rem 0;
51
- font-family: 'Monaco', 'Menlo', monospace;
52
- }
53
- .stats {
54
- display: grid;
55
- grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
56
- gap: 1rem;
57
- margin-top: 2rem;
58
- }
59
- .stat {
60
- background: rgba(255, 255, 255, 0.15);
61
- padding: 1rem;
62
- border-radius: 0.5rem;
63
- }
64
- .stat-label {
65
- font-size: 0.9rem;
66
- opacity: 0.8;
67
- }
68
- .stat-value {
69
- font-size: 1.5rem;
70
- font-weight: 700;
71
- margin-top: 0.25rem;
72
- }
73
- a {
74
- color: white;
75
- text-decoration: none;
76
- border-bottom: 2px solid rgba(255, 255, 255, 0.5);
77
- transition: border-color 0.2s;
78
- }
79
- a:hover {
80
- border-color: white;
81
- }
82
- </style>
83
- </head>
84
- <body>
85
- <div class="container">
86
- <div class="emoji">⚡</div>
87
- <h1>fonstr</h1>
88
- <p>Your Nostr relay is running!</p>
89
-
90
- <div class="relay-info">
91
- <p style="font-size: 1rem; margin-bottom: 1rem; opacity: 0.9;">Connect to your relay:</p>
92
- <code>ws://localhost:4444/relay</code>
93
-
94
- <div class="stats">
95
- <div class="stat">
96
- <div class="stat-label">Status</div>
97
- <div class="stat-value">✓ Online</div>
98
- </div>
99
- <div class="stat">
100
- <div class="stat-label">Protocol</div>
101
- <div class="stat-value">NIP-01</div>
102
- </div>
103
- <div class="stat">
104
- <div class="stat-label">Port</div>
105
- <div class="stat-value">4444</div>
106
- </div>
107
- </div>
108
- </div>
109
-
110
- <p style="font-size: 1rem;">
111
- Add this relay to your favorite Nostr client and start using it!<br>
112
- <a href="https://fonstr.com" target="_blank">Learn more about fonstr</a>
113
- </p>
114
-
115
- <p style="font-size: 0.9rem; opacity: 0.7; margin-top: 2rem;">
116
- Replace this page by editing <code style="font-size: 0.8rem;">index.html</code> in your data directory
117
- </p>
118
- </div>
119
- </body>
120
- </html>