javascript-solid-server 0.0.13 → 0.0.16

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.
Files changed (49) hide show
  1. package/.claude/settings.local.json +27 -1
  2. package/CTH.md +222 -0
  3. package/README.md +92 -3
  4. package/bin/jss.js +11 -1
  5. package/cth-config/application.yaml +2 -0
  6. package/cth-config/jss.ttl +6 -0
  7. package/cth-config/test-subjects.ttl +14 -0
  8. package/cth.env +19 -0
  9. package/package.json +1 -1
  10. package/scripts/test-cth-compat.js +3 -2
  11. package/src/auth/middleware.js +17 -7
  12. package/src/auth/token.js +44 -1
  13. package/src/config.js +7 -0
  14. package/src/handlers/container.js +49 -16
  15. package/src/handlers/resource.js +99 -32
  16. package/src/idp/accounts.js +11 -2
  17. package/src/idp/credentials.js +38 -38
  18. package/src/idp/index.js +112 -21
  19. package/src/idp/interactions.js +123 -11
  20. package/src/idp/provider.js +68 -2
  21. package/src/rdf/turtle.js +15 -2
  22. package/src/server.js +24 -0
  23. package/src/utils/url.js +52 -0
  24. package/src/wac/parser.js +43 -1
  25. package/test/idp.test.js +17 -14
  26. package/test/ldp.test.js +10 -5
  27. package/test-data-idp-accounts/.idp/accounts/3c1cd503-1d7f-4ba0-a3af-ebedf519594d.json +9 -0
  28. package/test-data-idp-accounts/.idp/accounts/_email_index.json +3 -0
  29. package/test-data-idp-accounts/.idp/accounts/_webid_index.json +3 -0
  30. package/test-data-idp-accounts/.idp/keys/jwks.json +22 -0
  31. package/test-dpop-flow.js +148 -0
  32. package/test-subjects.ttl +21 -0
  33. package/data/alice/.acl +0 -50
  34. package/data/alice/inbox/.acl +0 -50
  35. package/data/alice/index.html +0 -80
  36. package/data/alice/private/.acl +0 -32
  37. package/data/alice/public/test.json +0 -1
  38. package/data/alice/settings/.acl +0 -32
  39. package/data/alice/settings/prefs +0 -17
  40. package/data/alice/settings/privateTypeIndex +0 -7
  41. package/data/alice/settings/publicTypeIndex +0 -7
  42. package/data/bob/.acl +0 -50
  43. package/data/bob/inbox/.acl +0 -50
  44. package/data/bob/index.html +0 -80
  45. package/data/bob/private/.acl +0 -32
  46. package/data/bob/settings/.acl +0 -32
  47. package/data/bob/settings/prefs +0 -17
  48. package/data/bob/settings/privateTypeIndex +0 -7
  49. package/data/bob/settings/publicTypeIndex +0 -7
package/test/idp.test.js CHANGED
@@ -43,7 +43,8 @@ describe('Identity Provider', () => {
43
43
  assert.strictEqual(res.status, 200);
44
44
 
45
45
  const config = await res.json();
46
- assert.strictEqual(config.issuer, BASE_URL);
46
+ // Issuer has trailing slash for CTH compatibility
47
+ assert.strictEqual(config.issuer, BASE_URL + '/');
47
48
  assert.ok(config.authorization_endpoint);
48
49
  assert.ok(config.token_endpoint);
49
50
  assert.ok(config.jwks_uri);
@@ -259,17 +260,16 @@ describe('Identity Provider - Accounts', () => {
259
260
 
260
261
  describe('Identity Provider - Credentials Endpoint', () => {
261
262
  let server;
262
- const CREDS_DATA_DIR = './test-data-idp-creds';
263
+ // Use same data dir as other tests (DATA_ROOT is cached at module load)
264
+ const CREDS_DATA_DIR = './data';
263
265
  const CREDS_PORT = 3101;
264
266
  const CREDS_URL = `http://${TEST_HOST}:${CREDS_PORT}`;
265
267
 
266
268
  before(async () => {
267
- await fs.remove(CREDS_DATA_DIR);
268
- await fs.ensureDir(CREDS_DATA_DIR);
269
+ await fs.emptyDir(CREDS_DATA_DIR);
269
270
 
270
271
  server = createServer({
271
272
  logger: false,
272
- root: CREDS_DATA_DIR,
273
273
  idp: true,
274
274
  idpIssuer: CREDS_URL,
275
275
  });
@@ -277,7 +277,7 @@ describe('Identity Provider - Credentials Endpoint', () => {
277
277
  await server.listen({ port: CREDS_PORT, host: TEST_HOST });
278
278
 
279
279
  // Create a test user
280
- await fetch(`${CREDS_URL}/.pods`, {
280
+ const res = await fetch(`${CREDS_URL}/.pods`, {
281
281
  method: 'POST',
282
282
  headers: { 'Content-Type': 'application/json' },
283
283
  body: JSON.stringify({
@@ -286,11 +286,14 @@ describe('Identity Provider - Credentials Endpoint', () => {
286
286
  password: 'testpassword123',
287
287
  }),
288
288
  });
289
+ if (!res.ok) {
290
+ throw new Error(`Failed to create test user: ${res.status} ${await res.text()}`);
291
+ }
289
292
  });
290
293
 
291
294
  after(async () => {
292
295
  await server.close();
293
- await fs.remove(CREDS_DATA_DIR);
296
+ await fs.emptyDir(CREDS_DATA_DIR);
294
297
  });
295
298
 
296
299
  describe('GET /idp/credentials', () => {
@@ -366,7 +369,7 @@ describe('Identity Provider - Credentials Endpoint', () => {
366
369
  assert.ok(body.webid.includes('credtest'), 'should have webid');
367
370
  });
368
371
 
369
- it('should return simple token with webid for Bearer auth', async () => {
372
+ it('should return JWT token with webid claim', async () => {
370
373
  const res = await fetch(`${CREDS_URL}/idp/credentials`, {
371
374
  method: 'POST',
372
375
  headers: { 'Content-Type': 'application/json' },
@@ -378,15 +381,15 @@ describe('Identity Provider - Credentials Endpoint', () => {
378
381
 
379
382
  const body = await res.json();
380
383
 
381
- // Simple tokens have format: base64payload.signature
384
+ // JWT tokens have format: header.payload.signature
382
385
  const parts = body.access_token.split('.');
383
- assert.strictEqual(parts.length, 2, 'simple token has 2 parts');
386
+ assert.strictEqual(parts.length, 3, 'JWT token has 3 parts');
384
387
 
385
- // Decode the payload
386
- const payload = JSON.parse(Buffer.from(parts[0], 'base64url').toString());
388
+ // Decode the payload (second part)
389
+ const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString());
387
390
 
388
- assert.ok(payload.webId, 'token should have webId');
389
- assert.ok(payload.webId.includes('credtest'), 'webId should reference user');
391
+ assert.ok(payload.webid, 'token should have webid claim');
392
+ assert.ok(payload.webid.includes('credtest'), 'webid should reference user');
390
393
  assert.ok(payload.exp > payload.iat, 'should have valid expiry');
391
394
  });
392
395
 
package/test/ldp.test.js CHANGED
@@ -29,7 +29,8 @@ describe('LDP CRUD Operations', () => {
29
29
 
30
30
  describe('GET', () => {
31
31
  it('should return 404 for non-existent resource', async () => {
32
- const res = await request('/ldptest/nonexistent.json');
32
+ // Must use /public/ path for unauthenticated access
33
+ const res = await request('/ldptest/public/nonexistent.json');
33
34
  assertStatus(res, 404);
34
35
  });
35
36
 
@@ -149,14 +150,18 @@ describe('LDP CRUD Operations', () => {
149
150
  assertStatus(parent, 200);
150
151
  });
151
152
 
152
- it('should reject PUT to container path', async () => {
153
- const res = await request('/ldptest/public/invalid/', {
153
+ it('should create container with PUT to path ending in slash', async () => {
154
+ // Solid spec: PUT to path with trailing / creates container
155
+ const res = await request('/ldptest/public/new-container/', {
154
156
  method: 'PUT',
155
- body: 'cannot put to container',
156
157
  auth: 'ldptest'
157
158
  });
158
159
 
159
- assertStatus(res, 409);
160
+ assertStatus(res, 201);
161
+
162
+ // Verify it's a container
163
+ const verify = await request('/ldptest/public/new-container/');
164
+ assertHeaderContains(verify, 'Link', 'Container');
160
165
  });
161
166
  });
162
167
 
@@ -0,0 +1,9 @@
1
+ {
2
+ "id": "3c1cd503-1d7f-4ba0-a3af-ebedf519594d",
3
+ "email": "credtest@example.com",
4
+ "passwordHash": "$2b$10$h3cRwsgAo/4wEOyip6ckyOf6J.reHOzJzyZrM.LDfQdIWa3e/MkAu",
5
+ "webId": "http://localhost:3101/credtest/#me",
6
+ "podName": "credtest",
7
+ "createdAt": "2025-12-27T12:48:00.226Z",
8
+ "lastLogin": "2025-12-27T12:48:00.567Z"
9
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "credtest@example.com": "3c1cd503-1d7f-4ba0-a3af-ebedf519594d"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "http://localhost:3101/credtest/#me": "3c1cd503-1d7f-4ba0-a3af-ebedf519594d"
3
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "jwks": {
3
+ "keys": [
4
+ {
5
+ "kty": "EC",
6
+ "x": "NzQ-skj7cwbmI4Q_-vlQzoPYoQLWq_u34ln95VMcpnU",
7
+ "y": "H6gMaardV77boCWD4OTix1DsxdY-clIBw7I5xvvDDe8",
8
+ "crv": "P-256",
9
+ "d": "WrlpdJo_JidHFldBjU4Q6Wv_ULhAk1j-DTU6YlHxDAQ",
10
+ "kid": "4e655460-7c94-479c-9ed8-923aa8bfd77f",
11
+ "use": "sig",
12
+ "alg": "ES256",
13
+ "iat": 1766839680
14
+ }
15
+ ]
16
+ },
17
+ "cookieKeys": [
18
+ "CQXN03oU_rUqugGhwZgoiI7eZMgKJaPE_kyrT9lmTu4",
19
+ "jsJGLtKzYy-RJPZaAMZDpUcfY4-EtdqNOFS-Uiowk9w"
20
+ ],
21
+ "createdAt": "2025-12-27T12:48:00.136Z"
22
+ }
@@ -0,0 +1,148 @@
1
+ import * as jose from 'jose';
2
+ import crypto from 'crypto';
3
+
4
+ const BASE = 'http://localhost:4000';
5
+
6
+ // Create DPoP proof
7
+ async function createDpopProof(privateKey, publicJwk, method, url, ath = null) {
8
+ const payload = {
9
+ jti: crypto.randomUUID(),
10
+ htm: method,
11
+ htu: url,
12
+ iat: Math.floor(Date.now() / 1000),
13
+ };
14
+ if (ath) payload.ath = ath;
15
+
16
+ return new jose.SignJWT(payload)
17
+ .setProtectedHeader({ alg: 'ES256', typ: 'dpop+jwt', jwk: publicJwk })
18
+ .sign(privateKey);
19
+ }
20
+
21
+ async function main() {
22
+ console.log('=== Testing DPoP Auth Flow ===\n');
23
+
24
+ // 1. Generate key pair
25
+ const { privateKey, publicKey } = await jose.generateKeyPair('ES256');
26
+ const publicJwk = await jose.exportJWK(publicKey);
27
+ const jkt = await jose.calculateJwkThumbprint(publicJwk, 'sha256');
28
+ console.log('1. Generated DPoP key pair, thumbprint:', jkt.substring(0, 20) + '...\n');
29
+
30
+ // 2. Register client dynamically
31
+ console.log('2. Registering client...');
32
+ const regRes = await fetch(`${BASE}/idp/reg`, {
33
+ method: 'POST',
34
+ headers: { 'Content-Type': 'application/json' },
35
+ body: JSON.stringify({
36
+ redirect_uris: ['https://tester'],
37
+ token_endpoint_auth_method: 'none',
38
+ grant_types: ['authorization_code'],
39
+ response_types: ['code'],
40
+ }),
41
+ });
42
+ const client = await regRes.json();
43
+ console.log(' Client ID:', client.client_id, '\n');
44
+
45
+ // 3. Generate PKCE
46
+ const codeVerifier = crypto.randomBytes(32).toString('base64url');
47
+ const codeChallenge = crypto.createHash('sha256').update(codeVerifier).digest('base64url');
48
+ console.log('3. Generated PKCE challenge\n');
49
+
50
+ // 4. Authorization request - WITH dpop_jkt parameter
51
+ console.log('4. Starting authorization (with dpop_jkt)...');
52
+ const authUrl = new URL(`${BASE}/idp/auth`);
53
+ authUrl.searchParams.set('client_id', client.client_id);
54
+ authUrl.searchParams.set('redirect_uri', 'https://tester');
55
+ authUrl.searchParams.set('response_type', 'code');
56
+ authUrl.searchParams.set('scope', 'openid');
57
+ authUrl.searchParams.set('code_challenge', codeChallenge);
58
+ authUrl.searchParams.set('code_challenge_method', 'S256');
59
+ authUrl.searchParams.set('dpop_jkt', jkt); // KEY: Include dpop_jkt!
60
+
61
+ const authRes = await fetch(authUrl, { redirect: 'manual' });
62
+ const interactionUrl = authRes.headers.get('location');
63
+ console.log(' Redirected to:', interactionUrl ? interactionUrl.substring(0, 50) + '...' : 'none');
64
+ console.log(' Status:', authRes.status, '\n');
65
+
66
+ // 5. Get interaction session cookie
67
+ const rawCookies = authRes.headers.get('set-cookie') || '';
68
+ // Extract just name=value from each Set-Cookie, ignore attributes
69
+ const cookieValues = rawCookies.split(/, (?=[^;]+=[^;]+)/).map(c => c.split(';')[0]).join('; ');
70
+ console.log('5. Got cookies:', cookieValues ? cookieValues.substring(0, 80) + '...' : 'none\n');
71
+
72
+ // 6. Login
73
+ console.log('6. Logging in...');
74
+ const uid = interactionUrl ? interactionUrl.match(/interaction\/([^/?]+)/)?.[1] : null;
75
+ if (!uid) {
76
+ console.log(' ERROR: No interaction UID found');
77
+ return;
78
+ }
79
+ const loginRes = await fetch(`${BASE}/idp/interaction/${uid}`, {
80
+ method: 'POST',
81
+ headers: {
82
+ 'Content-Type': 'application/json',
83
+ Cookie: cookieValues,
84
+ },
85
+ body: JSON.stringify({ email: 'alice@example.com', password: 'alicepassword123' }),
86
+ });
87
+ let loginBody;
88
+ const loginText = await loginRes.text();
89
+ try {
90
+ loginBody = JSON.parse(loginText);
91
+ } catch (e) {
92
+ console.log(' Login response (text):', loginText.substring(0, 200));
93
+ return;
94
+ }
95
+ console.log(' Login response:', loginRes.status, loginBody.location ? loginBody.location.substring(0, 50) : '');
96
+
97
+ // 7. Follow auth resume
98
+ console.log('\n7. Following auth resume...');
99
+ const resumeUrl = loginBody.location;
100
+ if (!resumeUrl) {
101
+ console.log(' ERROR: No resume URL');
102
+ return;
103
+ }
104
+ const fullResumeUrl = resumeUrl.startsWith('http') ? resumeUrl : `${BASE}${resumeUrl}`;
105
+ const resumeRes = await fetch(fullResumeUrl, {
106
+ redirect: 'manual',
107
+ headers: { Cookie: cookieValues },
108
+ });
109
+ const callbackUrl = resumeRes.headers.get('location');
110
+ console.log(' Resume status:', resumeRes.status);
111
+ console.log(' Callback URL:', callbackUrl ? callbackUrl.substring(0, 80) + '...' : 'none');
112
+
113
+ // 8. Extract code
114
+ const codeMatch = callbackUrl ? callbackUrl.match(/code=([^&]+)/) : null;
115
+ const code = codeMatch ? codeMatch[1] : null;
116
+ if (!code) {
117
+ console.log(' ERROR: No code in callback');
118
+ return;
119
+ }
120
+ console.log(' Code:', code.substring(0, 20) + '...\n');
121
+
122
+ // 9. Token exchange with DPoP
123
+ console.log('8. Exchanging code for token (with DPoP)...');
124
+ const dpopProof = await createDpopProof(privateKey, publicJwk, 'POST', `${BASE}/idp/token`);
125
+ const tokenRes = await fetch(`${BASE}/idp/token`, {
126
+ method: 'POST',
127
+ headers: {
128
+ 'Content-Type': 'application/x-www-form-urlencoded',
129
+ DPoP: dpopProof,
130
+ },
131
+ body: new URLSearchParams({
132
+ grant_type: 'authorization_code',
133
+ code: code,
134
+ redirect_uri: 'https://tester',
135
+ client_id: client.client_id,
136
+ code_verifier: codeVerifier,
137
+ }).toString(),
138
+ });
139
+
140
+ console.log(' Token response status:', tokenRes.status);
141
+ const tokenBody = await tokenRes.text();
142
+ console.log(' Token response:', tokenBody.substring(0, 300));
143
+ }
144
+
145
+ main().catch(err => {
146
+ console.error('Error:', err.message);
147
+ console.error(err.stack);
148
+ });
@@ -0,0 +1,21 @@
1
+ @base <https://github.com/solid/conformance-test-harness/> .
2
+ @prefix solid-test: <https://github.com/solid/conformance-test-harness/vocab#> .
3
+ @prefix doap: <http://usefulinc.com/ns/doap#> .
4
+ @prefix earl: <http://www.w3.org/ns/earl#> .
5
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
6
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
7
+
8
+ <jss>
9
+ a earl:Software, earl:TestSubject ;
10
+ doap:name "JavaScript Solid Server"@en ;
11
+ doap:release <jss#test-subject-release> ;
12
+ doap:developer <https://github.com/JavaScriptSolidServer> ;
13
+ doap:homepage <https://github.com/JavaScriptSolidServer/JavaScriptSolidServer> ;
14
+ doap:description "A minimal, fast, JSON-LD native Solid server."@en ;
15
+ doap:programming-language "JavaScript"@en ;
16
+ solid-test:skip "acp", "wac", "wac-allow-public" ;
17
+ rdfs:comment "JSON-LD first Solid server with built-in IdP"@en .
18
+
19
+ <jss#test-subject-release>
20
+ doap:revision "0.0.14"@en ;
21
+ doap:created "2025-12-27"^^xsd:date .
package/data/alice/.acl DELETED
@@ -1,50 +0,0 @@
1
- {
2
- "@context": {
3
- "acl": "http://www.w3.org/ns/auth/acl#",
4
- "foaf": "http://xmlns.com/foaf/0.1/"
5
- },
6
- "@graph": [
7
- {
8
- "@id": "#owner",
9
- "@type": "acl:Authorization",
10
- "acl:agent": {
11
- "@id": "http://localhost:3457/alice/#me"
12
- },
13
- "acl:accessTo": {
14
- "@id": "http://localhost:3457/alice/"
15
- },
16
- "acl:mode": [
17
- {
18
- "@id": "acl:Read"
19
- },
20
- {
21
- "@id": "acl:Write"
22
- },
23
- {
24
- "@id": "acl:Control"
25
- }
26
- ],
27
- "acl:default": {
28
- "@id": "http://localhost:3457/alice/"
29
- }
30
- },
31
- {
32
- "@id": "#public",
33
- "@type": "acl:Authorization",
34
- "acl:agentClass": {
35
- "@id": "foaf:Agent"
36
- },
37
- "acl:accessTo": {
38
- "@id": "http://localhost:3457/alice/"
39
- },
40
- "acl:mode": [
41
- {
42
- "@id": "acl:Read"
43
- }
44
- ],
45
- "acl:default": {
46
- "@id": "http://localhost:3457/alice/"
47
- }
48
- }
49
- ]
50
- }
@@ -1,50 +0,0 @@
1
- {
2
- "@context": {
3
- "acl": "http://www.w3.org/ns/auth/acl#",
4
- "foaf": "http://xmlns.com/foaf/0.1/"
5
- },
6
- "@graph": [
7
- {
8
- "@id": "#owner",
9
- "@type": "acl:Authorization",
10
- "acl:agent": {
11
- "@id": "http://localhost:3457/alice/#me"
12
- },
13
- "acl:accessTo": {
14
- "@id": "http://localhost:3457/alice/inbox/"
15
- },
16
- "acl:default": {
17
- "@id": "http://localhost:3457/alice/inbox/"
18
- },
19
- "acl:mode": [
20
- {
21
- "@id": "acl:Read"
22
- },
23
- {
24
- "@id": "acl:Write"
25
- },
26
- {
27
- "@id": "acl:Control"
28
- }
29
- ]
30
- },
31
- {
32
- "@id": "#public",
33
- "@type": "acl:Authorization",
34
- "acl:agentClass": {
35
- "@id": "foaf:Agent"
36
- },
37
- "acl:accessTo": {
38
- "@id": "http://localhost:3457/alice/inbox/"
39
- },
40
- "acl:default": {
41
- "@id": "http://localhost:3457/alice/inbox/"
42
- },
43
- "acl:mode": [
44
- {
45
- "@id": "acl:Append"
46
- }
47
- ]
48
- }
49
- ]
50
- }
@@ -1,80 +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">
6
- <title>alice's Profile</title>
7
- <script type="application/ld+json">
8
- {
9
- "@context": {
10
- "foaf": "http://xmlns.com/foaf/0.1/",
11
- "solid": "http://www.w3.org/ns/solid/terms#",
12
- "schema": "http://schema.org/",
13
- "pim": "http://www.w3.org/ns/pim/space#",
14
- "ldp": "http://www.w3.org/ns/ldp#",
15
- "inbox": {
16
- "@id": "ldp:inbox",
17
- "@type": "@id"
18
- },
19
- "storage": {
20
- "@id": "pim:storage",
21
- "@type": "@id"
22
- },
23
- "oidcIssuer": {
24
- "@id": "solid:oidcIssuer",
25
- "@type": "@id"
26
- },
27
- "preferencesFile": {
28
- "@id": "pim:preferencesFile",
29
- "@type": "@id"
30
- }
31
- },
32
- "@graph": [
33
- {
34
- "@id": "http://localhost:3457/alice/",
35
- "@type": "foaf:PersonalProfileDocument",
36
- "foaf:maker": {
37
- "@id": "http://localhost:3457/alice/#me"
38
- },
39
- "foaf:primaryTopic": {
40
- "@id": "http://localhost:3457/alice/#me"
41
- }
42
- },
43
- {
44
- "@id": "http://localhost:3457/alice/#me",
45
- "@type": [
46
- "foaf:Person",
47
- "schema:Person"
48
- ],
49
- "foaf:name": "alice",
50
- "inbox": "http://localhost:3457/alice/inbox/",
51
- "storage": "http://localhost:3457/alice/",
52
- "oidcIssuer": "http://localhost:3457",
53
- "preferencesFile": "http://localhost:3457/alice/settings/prefs"
54
- }
55
- ]
56
- }
57
- </script>
58
- <style>
59
- body { font-family: system-ui, sans-serif; max-width: 600px; margin: 2rem auto; padding: 0 1rem; }
60
- h1 { color: #333; }
61
- .card { background: #f5f5f5; padding: 1.5rem; border-radius: 8px; }
62
- dt { font-weight: bold; margin-top: 1rem; }
63
- dd { margin-left: 0; color: #666; }
64
- a { color: #7c4dff; }
65
- </style>
66
- </head>
67
- <body>
68
- <div class="card">
69
- <h1>alice</h1>
70
- <dl>
71
- <dt>WebID</dt>
72
- <dd><a href="http://localhost:3457/alice/#me">http://localhost:3457/alice/#me</a></dd>
73
- <dt>Storage</dt>
74
- <dd><a href="http://localhost:3457/alice/">http://localhost:3457/alice/</a></dd>
75
- <dt>Inbox</dt>
76
- <dd><a href="http://localhost:3457/alice/inbox/">http://localhost:3457/alice/inbox/</a></dd>
77
- </dl>
78
- </div>
79
- </body>
80
- </html>
@@ -1,32 +0,0 @@
1
- {
2
- "@context": {
3
- "acl": "http://www.w3.org/ns/auth/acl#",
4
- "foaf": "http://xmlns.com/foaf/0.1/"
5
- },
6
- "@graph": [
7
- {
8
- "@id": "#owner",
9
- "@type": "acl:Authorization",
10
- "acl:agent": {
11
- "@id": "http://localhost:3457/alice/#me"
12
- },
13
- "acl:accessTo": {
14
- "@id": "http://localhost:3457/alice/private/"
15
- },
16
- "acl:mode": [
17
- {
18
- "@id": "acl:Read"
19
- },
20
- {
21
- "@id": "acl:Write"
22
- },
23
- {
24
- "@id": "acl:Control"
25
- }
26
- ],
27
- "acl:default": {
28
- "@id": "http://localhost:3457/alice/private/"
29
- }
30
- }
31
- ]
32
- }
@@ -1 +0,0 @@
1
- {"@id":"#test","http://example.org/value":42}
@@ -1,32 +0,0 @@
1
- {
2
- "@context": {
3
- "acl": "http://www.w3.org/ns/auth/acl#",
4
- "foaf": "http://xmlns.com/foaf/0.1/"
5
- },
6
- "@graph": [
7
- {
8
- "@id": "#owner",
9
- "@type": "acl:Authorization",
10
- "acl:agent": {
11
- "@id": "http://localhost:3457/alice/#me"
12
- },
13
- "acl:accessTo": {
14
- "@id": "http://localhost:3457/alice/settings/"
15
- },
16
- "acl:mode": [
17
- {
18
- "@id": "acl:Read"
19
- },
20
- {
21
- "@id": "acl:Write"
22
- },
23
- {
24
- "@id": "acl:Control"
25
- }
26
- ],
27
- "acl:default": {
28
- "@id": "http://localhost:3457/alice/settings/"
29
- }
30
- }
31
- ]
32
- }
@@ -1,17 +0,0 @@
1
- {
2
- "@context": {
3
- "solid": "http://www.w3.org/ns/solid/terms#",
4
- "pim": "http://www.w3.org/ns/pim/space#",
5
- "publicTypeIndex": {
6
- "@id": "solid:publicTypeIndex",
7
- "@type": "@id"
8
- },
9
- "privateTypeIndex": {
10
- "@id": "solid:privateTypeIndex",
11
- "@type": "@id"
12
- }
13
- },
14
- "@id": "http://localhost:3457/alice/settings/prefs",
15
- "publicTypeIndex": "http://localhost:3457/alice/settings/publicTypeIndex",
16
- "privateTypeIndex": "http://localhost:3457/alice/settings/privateTypeIndex"
17
- }
@@ -1,7 +0,0 @@
1
- {
2
- "@context": {
3
- "solid": "http://www.w3.org/ns/solid/terms#"
4
- },
5
- "@id": "http://localhost:3457/alice/settings/privateTypeIndex",
6
- "@type": "solid:TypeIndex"
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "@context": {
3
- "solid": "http://www.w3.org/ns/solid/terms#"
4
- },
5
- "@id": "http://localhost:3457/alice/settings/publicTypeIndex",
6
- "@type": "solid:TypeIndex"
7
- }
package/data/bob/.acl DELETED
@@ -1,50 +0,0 @@
1
- {
2
- "@context": {
3
- "acl": "http://www.w3.org/ns/auth/acl#",
4
- "foaf": "http://xmlns.com/foaf/0.1/"
5
- },
6
- "@graph": [
7
- {
8
- "@id": "#owner",
9
- "@type": "acl:Authorization",
10
- "acl:agent": {
11
- "@id": "http://localhost:3457/bob/#me"
12
- },
13
- "acl:accessTo": {
14
- "@id": "http://localhost:3457/bob/"
15
- },
16
- "acl:mode": [
17
- {
18
- "@id": "acl:Read"
19
- },
20
- {
21
- "@id": "acl:Write"
22
- },
23
- {
24
- "@id": "acl:Control"
25
- }
26
- ],
27
- "acl:default": {
28
- "@id": "http://localhost:3457/bob/"
29
- }
30
- },
31
- {
32
- "@id": "#public",
33
- "@type": "acl:Authorization",
34
- "acl:agentClass": {
35
- "@id": "foaf:Agent"
36
- },
37
- "acl:accessTo": {
38
- "@id": "http://localhost:3457/bob/"
39
- },
40
- "acl:mode": [
41
- {
42
- "@id": "acl:Read"
43
- }
44
- ],
45
- "acl:default": {
46
- "@id": "http://localhost:3457/bob/"
47
- }
48
- }
49
- ]
50
- }