Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lws10-test-suite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
98 changes: 98 additions & 0 deletions lws10-test-suite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# LWS Protocol 1.0 Test Suite

Test suite for the [Linked Web Storage Protocol 1.0](https://www.w3.org/TR/lws10-core/)
and its authentication suite specifications:

- [LWS 1.0 Authentication Suite: Self-signed Identity using did:key](https://www.w3.org/TR/lws10-authn-ssi-did-key/)
- [LWS 1.0 Authentication Suite: OpenID Connect](https://www.w3.org/TR/lws10-authn-openid/)
- [LWS 1.0 Authentication Suite: SAML 2.0](https://www.w3.org/TR/lws10-authn-saml/)

## Directory Structure

```
tests/
├── context.jsonld # Shared JSON-LD context for all manifests
├── manifest.jsonld # Root manifest (core protocol tests)
├── auth/
│ ├── did-key/manifest.jsonld # did:key authentication suite tests
│ ├── oidc/manifest.jsonld # OpenID Connect authentication suite tests
│ └── saml/manifest.jsonld # SAML 2.0 authentication suite tests
├── containers/
│ └── alice-notes.json # Example container representation body
├── linksets/
│ ├── alice-notes.meta.json # Linkset for /alice/notes/
│ └── shoppinglist.meta.json # Linkset for /alice/notes/shoppinglist.txt
└── resources/
├── storage-description.json # Storage description resource body
├── authorization-server-metadata.json # AS metadata body
├── shoppinglist.txt # Data resource body
├── token-response-200.json # Successful token exchange response
└── token-response-400.json # Failed token exchange response
```

## Conventions

### Inline vs. by-reference properties

Properties that carry their value directly use a plain JSON name:

```json
"body": "some content"
```

Properties that reference an external resource by URL append `URL` to the name:

```json
"bodyURL": "../containers/alice-notes.json"
```

The same convention applies to `href` / `hrefTemplate` for Link header values, and
`url` / `urlTemplate` for request targets.

### Test types

| Type | Meaning |
|------|---------|
| `lwst:ValidationTest` | The server MUST respond as described for conformance |
| `lwst:NegativeTest` | The server MUST reject the request as described |

### Traits (applied to tests for filtering)

`Get`, `Post`, `Put`, `Delete`, `Patch` — HTTP method used
`Public` — no authentication required
`Private` — resource requires authentication/authorization
`Authn` — exercises authentication behaviour
`Authz` — exercises authorization behaviour
`Container` — targets a Container resource
`DataResource` — targets a DataResource
`Discovery` — exercises service/storage description discovery

### Authorization roles (ODRL-based)

| Compact name | Meaning |
|-------------|---------|
| `Role-Public` | Any agent, authenticated or not |
| `Role-Authenticated` | Any agent that presents a valid access token |
| `Role-Owner` | The resource manager (owner) of the storage |

### Prerequisite hierarchy

Each test's `prereqs.hierarchy` array describes the resources (and their access policies)
that a test harness MUST establish before issuing the test request. An empty array means
no prior state is required.

### Authentication

`prereqs.authentication` and `request.authentication` hold the WebID/subject URI of the
agent to authenticate as, or `null` for anonymous requests.

## Test certificate authority

Tests that require authentication may use a test CA whose certificate is distributed
alongside this test suite. Implementations SHOULD accept this CA only in test/non-production
environments.

## Status values

All tests start with `mf:Proposed`. They advance to `mf:Approved` once an independent
implementation demonstrates conformance.
1 change: 1 addition & 0 deletions lws10-test-suite/auth/did-key
1 change: 1 addition & 0 deletions lws10-test-suite/auth/oidc
1 change: 1 addition & 0 deletions lws10-test-suite/auth/saml
17 changes: 17 additions & 0 deletions lws10-test-suite/containers/alice-notes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"@context": "https://www.w3.org/ns/lws/v1",
"id": "https://storage.example/alice/notes/",
"type": "Container",
"items": [
{
"id": "https://storage.example/alice/notes/shoppinglist.txt",
"type": "DataResource",
"contentType": "text/plain",
"size": 47
},
{
"id": "https://storage.example/alice/notes/ideas/",
"type": "Container"
}
]
}
94 changes: 94 additions & 0 deletions lws10-test-suite/context.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{
"@context": {
"@vocab": "https://www.w3.org/ns/lws-tests/v1#",

"lws": "https://www.w3.org/ns/lws/v1#",
"lwst": "https://www.w3.org/ns/lws-tests/v1#",
"mf": "https://www.w3.org/ns/test-manifest#",
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
"xsd": "http://www.w3.org/2001/XMLSchema#",
"odrl": "http://www.w3.org/ns/odrl/2/",

"id": "@id",
"type": "@type",
"comment": "rdfs:comment",
"label": "rdfs:label",

"name": {"@id": "mf:name", "@type": "xsd:string"},
"entries": {"@id": "mf:entries","@container": "@list", "@type": "@id"},
"status": {"@id": "mf:status", "@type": "@vocab"},
"include": {"@id": "mf:include","@type": "@id", "@container": "@list"},

"traits": {"@id": "lwst:traits", "@type": "@vocab", "@container": "@set"},

"prereqs": {"@id": "lwst:prereqs"},
"hierarchy": {"@id": "lwst:hierarchy", "@container": "@list"},
"authentication": {"@id": "lwst:authentication"},
"authorization": {"@id": "lwst:authorization"},

"url": {"@id": "lwst:url", "@type": "@id"},
"urlTemplate": {"@id": "lwst:url", "@type": "xsd:string"},

"read": {"@id": "odrl:read", "@type": "@vocab"},
"write": {"@id": "odrl:write", "@type": "@vocab"},
"append": {"@id": "odrl:use", "@type": "@vocab"},
"control": {"@id": "odrl:modify","@type": "@vocab"},

"request": {"@id": "lwst:request"},
"method": {"@id": "lwst:method", "@type": "xsd:string"},
"slug": {"@id": "lwst:slug", "@type": "xsd:string"},
"contentType": {"@id": "lwst:contentType", "@type": "xsd:string"},

"linkHeaders": {"@id": "lwst:linkHeaders", "@container": "@list"},
"otherHeaders": {"@id": "lwst:otherHeaders", "@container": "@list"},
"rel": {"@id": "lwst:rel", "@type": "xsd:string"},
"href": {"@id": "lwst:href", "@type": "@id"},
"hrefTemplate": {"@id": "lwst:href", "@type": "xsd:string"},
"mediaType": {"@id": "lwst:mediaType", "@type": "xsd:string"},
"headerName": {"@id": "lwst:headerName", "@type": "xsd:string"},
"headerValue": {"@id": "lwst:headerValue", "@type": "xsd:string"},

"body": {"@id": "lwst:body", "@type": "xsd:string"},
"bodyURL": {"@id": "lwst:body", "@type": "@id"},

"response": {"@id": "lwst:response"},
"statusCode": {"@id": "lwst:statusCode", "@type": "xsd:integer"},
"authenticationChallenge": {"@id": "lwst:authenticationChallenge"},
"authorizationHint": {"@id": "lwst:authorizationHint"},

"wwwAuthenticate": {"@id": "lwst:wwwAuthenticate", "@type": "xsd:string"},
"asUri": {"@id": "lwst:asUri", "@type": "@id"},
"realm": {"@id": "lwst:realm", "@type": "@id"},

"locationURL": {"@id": "lwst:location", "@type": "@id"},

"authSuites": {"@id": "lwst:authSuites", "@type": "@id", "@container": "@set"},
"facets": {"@id": "lwst:facets", "@type": "@id", "@container": "@set"},

"Role-Public": "lwst:Role-Public",
"Role-Owner": "lwst:Role-Owner",
"Role-Authenticated": "lwst:Role-Authenticated",

"Proposed": "mf:Proposed",
"Approved": "mf:Approved",
"Pending": "mf:Pending",

"ValidationTest": "lwst:ValidationTest",
"NegativeTest": "lwst:NegativeTest",
"Manifest": "mf:Manifest",

"Get": "lwst:Get",
"Post": "lwst:Post",
"Put": "lwst:Put",
"Delete": "lwst:Delete",
"Patch": "lwst:Patch",
"Public": "lwst:Public",
"Private": "lwst:Private",
"Authn": "lwst:Authn",
"Authz": "lwst:Authz",
"Container": "lwst:Container",
"DataResource": "lwst:DataResource",
"Discovery": "lwst:Discovery"
}
}
22 changes: 22 additions & 0 deletions lws10-test-suite/linksets/alice-notes.meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"linkset": [
{
"anchor": "https://storage.example/alice/notes/",
"https://www.w3.org/ns/lws#storageDescription": [
{ "href": "https://storage.example/alice/description" }
],
"up": [
{ "href": "https://storage.example/alice/" }
],
"type": [
{ "href": "https://www.w3.org/ns/lws#Container" }
],
"linkset": [
{
"href": "https://storage.example/alice/notes/.meta",
"type": "application/linkset+json"
}
]
}
]
}
22 changes: 22 additions & 0 deletions lws10-test-suite/linksets/shoppinglist.meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"linkset": [
{
"anchor": "https://storage.example/alice/notes/shoppinglist.txt",
"https://www.w3.org/ns/lws#storageDescription": [
{ "href": "https://storage.example/alice/description" }
],
"up": [
{ "href": "https://storage.example/alice/notes/" }
],
"type": [
{ "href": "https://www.w3.org/ns/lws#DataResource" }
],
"linkset": [
{
"href": "https://storage.example/alice/notes/shoppinglist.txt.meta",
"type": "application/linkset+json"
}
]
}
]
}
Loading