Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
2ecc531
[maven-release-plugin] prepare for next development iteration
namedgraph Dec 12, 2025
864183e
Simplified client-side refresh after OAuth login
namedgraph Dec 12, 2025
27bf9ce
Make sure proxy passes on the response status
namedgraph Dec 14, 2025
21d2ab0
NPE fix
namedgraph Dec 14, 2025
a7399f3
`ldh:origin` renamed to `lapp:origin`
namedgraph Dec 20, 2025
b385d45
Replaced document-level layout mode tabs with a mode dropdown
namedgraph Dec 22, 2025
816bfd7
View mode tabs replaced with a dropdown
namedgraph Dec 23, 2025
70a0b12
Optional view heading
namedgraph Dec 24, 2025
0a7398f
Fixed connection leaks
namedgraph Jan 1, 2026
9af745d
Closing client responss
namedgraph Jan 2, 2026
9e6cfb0
Test fix
namedgraph Jan 2, 2026
7b58db2
LinkedDataHub packages (#259)
namedgraph Jan 2, 2026
d0bb33b
Remove volumes in the GH action
namedgraph Jan 3, 2026
6cb0532
Test changes
namedgraph Jan 3, 2026
978e174
Banning stylesheet URLs when uninstalling package
namedgraph Jan 3, 2026
0081255
Test fix
namedgraph Jan 3, 2026
4b8feb7
Refactored install/uninstall endpoints
namedgraph Jan 3, 2026
d408109
Debug output
namedgraph Jan 3, 2026
a6e2b57
Test debug output
namedgraph Jan 3, 2026
1c36be1
Fixed Docker command
namedgraph Jan 3, 2026
736a9a7
Test debug output
namedgraph Jan 3, 2026
bd637a3
curl call change
namedgraph Jan 3, 2026
1f84753
Debug output
namedgraph Jan 3, 2026
39cf849
Debug output
namedgraph Jan 3, 2026
4a90c85
Debug output
namedgraph Jan 4, 2026
a449edd
Wait loops
namedgraph Jan 4, 2026
80ccb52
Test filter
namedgraph Jan 4, 2026
8fb2597
Revert "Wait loops"
namedgraph Jan 4, 2026
5dffefa
Test fixes
namedgraph Jan 4, 2026
69333d5
`regenerateMasterStylesheet` refactoring
namedgraph Jan 4, 2026
b7e6b64
Test fix
namedgraph Jan 4, 2026
8ab25d9
Debug output
namedgraph Jan 4, 2026
52fe095
Debug output
namedgraph Jan 4, 2026
3295cdb
Debug Varnish cache
namedgraph Jan 4, 2026
e815e81
Debug output
namedgraph Jan 5, 2026
34a132f
Debug output
namedgraph Jan 5, 2026
b875af4
Purge stylesheet from Varnish during installation
namedgraph Jan 5, 2026
d25dbaf
Sleep before requesting stylesheet
namedgraph Jan 5, 2026
98cb64e
Increase sleep
namedgraph Jan 5, 2026
cda5a9a
Run all tests
namedgraph Jan 5, 2026
a39792d
HTTP tests to use CLI scripts
namedgraph Jan 5, 2026
7b1e834
CLI script fixes
namedgraph Jan 5, 2026
1ebf6a6
Web-Client version bump
namedgraph Jan 6, 2026
4c1aab4
Incorporated AtomGraph Server code
namedgraph Jan 6, 2026
ec4e7e6
README update
namedgraph Jan 6, 2026
b9f5c2a
Handle `PATCH` that deletes all document triples as `DELETE`
namedgraph Jan 9, 2026
15994ed
Application settings feature (#264)
namedgraph Jan 10, 2026
7236501
CHANGELOG update
namedgraph Jan 10, 2026
089da77
Merge branch 'develop' of github.com:AtomGraph/LinkedDataHub into dev…
namedgraph Jan 10, 2026
a5363ae
Callback promise for the settings form
namedgraph Jan 10, 2026
3c7877d
Replaced `ldh:ModalFormSubmit` template with promises
namedgraph Jan 10, 2026
4874164
Moved modal form-related templates
namedgraph Jan 11, 2026
c847873
`Add` endpoint does not need to extend `Graph`
namedgraph Jan 11, 2026
96f8610
Extend `DirectGraphStoreImpl` (#266)
namedgraph Jan 13, 2026
5cc5713
Web-Client version bump
namedgraph Jan 13, 2026
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
4 changes: 2 additions & 2 deletions .github/workflows/http-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
run: ./run.sh "$PWD/ssl/owner/cert.pem" "${{ secrets.HTTP_TEST_OWNER_CERT_PASSWORD }}" "$PWD/ssl/secretary/cert.pem" "${{ secrets.HTTP_TEST_SECRETARY_CERT_PASSWORD }}"
shell: bash
working-directory: http-tests
- name: Stop Docker containers
run: docker compose --env-file ./http-tests/.env down
- name: Stop Docker containers and remove volumes
run: docker compose --env-file ./http-tests/.env down -v
- name: Remove Docker containers
run: docker compose --env-file ./http-tests/.env rm -f
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## [5.2.0] - 2026-01-14
### Added
- Application settings form with modal UI for editing dataspace configuration
- Settings endpoint (`/settings`) with `GET` and `PATCH` support for dataspace settings
- HTTP tests for the settings endpoint
- LinkedDataHub packages system with install/uninstall functionality

### Changed
- Core library refactored Graph Store Protocol implementation - split into `GraphStoreBase` (common functionality), `DirectGraphStoreImpl` (direct graph identification), and `GraphStoreImpl` (indirect graph identification with query parameters)
- Incorporated AtomGraph Server code directly into LinkedDataHub codebase
- System configuration dataset now uses named graphs instead of default graph
- Web-Client dependency version bump
- CLI scripts improved for better parameter handling

## [5.1.0] - 2025-12-12
### Added
- ORCID OpenID Connect login support with JWT token verification
Expand Down
24 changes: 23 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,26 @@ export PATH="$(find bin -type d -exec realpath {} \; | tr '\n' ':')$PATH"
- XSLT stylesheets are processed during build to inline XML entities
- Saxon-JS SEF files are generated during Maven package phase for client-side XSLT
- WebID certificates are required for authenticated API access
- The system expects Jena CLI tools to be available (`JENA_HOME` environment variable)
- The system expects Jena CLI tools to be available (`JENA_HOME` environment variable)

## Debugging Test Failures

When HTTP tests fail:
1. NEVER speculate about failures - always add debug output first
2. Add echo statements showing:
- The actual values being tested
- The expected values
- HTTP response codes and bodies where relevant
3. Run the test to see actual output
4. Only then diagnose and fix

Example debug pattern:
```bash
result=$(curl ...)
expected="..."
echo "DEBUG: Expected: $expected"
echo "DEBUG: Got: $result"
if [ "$result" != "$expected" ]; then
echo "DEBUG: Mismatch!"
exit 1
fi
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ The options are described in more detail in the [configuration documentation](ht

If you need to start fresh and wipe the existing setup (e.g. after configuring a new base URI), you can do that using
```shell
sudo rm -rf data uploads && docker-compose down -v
sudo rm -rf fuseki uploads ssl datasets && docker-compose down -v
```

_:warning: This will **remove the persisted data and files** as well as Docker volumes._
Expand Down Expand Up @@ -266,7 +266,6 @@ See the [Web-Algebra repository](https://github.com/AtomGraph/Web-Algebra) for s

LinkedDataHub includes an HTTP [test suite](https://github.com/AtomGraph/LinkedDataHub/tree/master/http-tests). The server implementation is also covered by the [Processor test suite](https://github.com/AtomGraph/Processor/tree/master/http-tests).

![HTTP-tests](https://github.com/AtomGraph/LinkedDataHub/actions/workflows/http-tests.yml/badge.svg)
![HTTP-tests](https://github.com/AtomGraph/LinkedDataHub/actions/workflows/http-tests.yml/badge.svg)

## Dependencies
Expand All @@ -287,8 +286,9 @@ LinkedDataHub includes an HTTP [test suite](https://github.com/AtomGraph/LinkedD
* [java-jwt](https://github.com/auth0/java-jwt)
* [ExpiringMap](https://github.com/jhalterman/expiringmap)
* [CSV2RDF](https://github.com/AtomGraph/CSV2RDF)
* [Processor](https://github.com/AtomGraph/Processor)
* [Web-Client](https://github.com/AtomGraph/Web-Client)
* [Twirl](https://github.com/AtomGraph/Twirl)
* [jena-shacl](https://mvnrepository.com/artifact/org.apache.jena/jena-shacl)

### Docker

Expand Down
1 change: 1 addition & 0 deletions bin/admin/clear-ontology.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
set -eo pipefail

print_usage()
{
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
104 changes: 104 additions & 0 deletions bin/admin/packages/install-package.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/usr/bin/env bash
set -eo pipefail

print_usage()
{
printf "Installs a LinkedDataHub package.\n"
printf "\n"
printf "Usage: %s options\n" "$0"
printf "\n"
printf "Options:\n"
printf " -b, --base BASE_URL Base URL of the application\n"
printf " -f, --cert-pem-file CERT_FILE .pem file with the WebID certificate of the agent\n"
printf " -p, --cert-password CERT_PASSWORD Password of the WebID certificate\n"
printf " --proxy PROXY_URL The host this request will be proxied through (optional)\n"
printf " --package PACKAGE_URI URI of the package to install (e.g., https://packages.linkeddatahub.com/skos/#this)\n"
printf "\n"
printf "Example:\n"
printf " %s -b https://localhost:4443/ -f ssl/owner/cert.pem -p Password --package https://packages.linkeddatahub.com/skos/#this\n" "$0"
}

hash curl 2>/dev/null || { echo >&2 "curl not on \$PATH. Aborting."; exit 1; }

unknown=()
while [[ $# -gt 0 ]]
do
key="$1"

case $key in
-b|--base)
base="$2"
shift # past argument
shift # past value
;;
-f|--cert-pem-file)
cert_pem_file="$2"
shift # past argument
shift # past value
;;
-p|--cert-password)
cert_password="$2"
shift # past argument
shift # past value
;;
--proxy)
proxy="$2"
shift # past argument
shift # past value
;;
--package)
package_uri="$2"
shift # past argument
shift # past value
;;
*) # unknown option
unknown+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
set -- "${unknown[@]}" # restore args

if [ -z "$base" ] ; then
print_usage
exit 1
fi
if [ -z "$cert_pem_file" ] ; then
print_usage
exit 1
fi
if [ -z "$cert_password" ] ; then
print_usage
exit 1
fi
if [ -z "$package_uri" ] ; then
print_usage
exit 1
fi

# Convert base URL to admin base URL
admin_uri() {
local uri="$1"
echo "$uri" | sed 's|://|://admin.|'
}

admin_base=$(admin_uri "$base")
target_url="${admin_base}packages/install"

if [ -n "$proxy" ]; then
admin_proxy=$(admin_uri "$proxy")
# rewrite target hostname to proxy hostname
url_host=$(echo "$target_url" | cut -d '/' -f 1,2,3)
proxy_host=$(echo "$admin_proxy" | cut -d '/' -f 1,2,3)
final_url="${target_url/$url_host/$proxy_host}"
else
final_url="$target_url"
fi

# POST to packages/install endpoint
curl -k -f -s -w "%{http_code}\n" -E "$cert_pem_file":"$cert_password" \
-X POST \
-H "Accept: text/turtle" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "package-uri=${package_uri}" \
"${final_url}"
104 changes: 104 additions & 0 deletions bin/admin/packages/uninstall-package.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/usr/bin/env bash
set -eo pipefail

print_usage()
{
printf "Uninstalls a LinkedDataHub package.\n"
printf "\n"
printf "Usage: %s options\n" "$0"
printf "\n"
printf "Options:\n"
printf " -b, --base BASE_URL Base URL of the application\n"
printf " -f, --cert-pem-file CERT_FILE .pem file with the WebID certificate of the agent\n"
printf " -p, --cert-password CERT_PASSWORD Password of the WebID certificate\n"
printf " --proxy PROXY_URL The host this request will be proxied through (optional)\n"
printf " --package PACKAGE_URI URI of the package to uninstall (e.g., https://packages.linkeddatahub.com/skos/#this)\n"
printf "\n"
printf "Example:\n"
printf " %s -b https://localhost:4443/ -f ssl/owner/cert.pem -p Password --package https://packages.linkeddatahub.com/skos/#this\n" "$0"
}

hash curl 2>/dev/null || { echo >&2 "curl not on \$PATH. Aborting."; exit 1; }

unknown=()
while [[ $# -gt 0 ]]
do
key="$1"

case $key in
-b|--base)
base="$2"
shift # past argument
shift # past value
;;
-f|--cert-pem-file)
cert_pem_file="$2"
shift # past argument
shift # past value
;;
-p|--cert-password)
cert_password="$2"
shift # past argument
shift # past value
;;
--proxy)
proxy="$2"
shift # past argument
shift # past value
;;
--package)
package_uri="$2"
shift # past argument
shift # past value
;;
*) # unknown option
unknown+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
set -- "${unknown[@]}" # restore args

if [ -z "$base" ] ; then
print_usage
exit 1
fi
if [ -z "$cert_pem_file" ] ; then
print_usage
exit 1
fi
if [ -z "$cert_password" ] ; then
print_usage
exit 1
fi
if [ -z "$package_uri" ] ; then
print_usage
exit 1
fi

# Convert base URL to admin base URL
admin_uri() {
local uri="$1"
echo "$uri" | sed 's|://|://admin.|'
}

admin_base=$(admin_uri "$base")
target_url="${admin_base}packages/uninstall"

if [ -n "$proxy" ]; then
admin_proxy=$(admin_uri "$proxy")
# rewrite target hostname to proxy hostname
url_host=$(echo "$target_url" | cut -d '/' -f 1,2,3)
proxy_host=$(echo "$admin_proxy" | cut -d '/' -f 1,2,3)
final_url="${target_url/$url_host/$proxy_host}"
else
final_url="$target_url"
fi

# POST to packages/uninstall endpoint
curl -k -f -s -w "%{http_code}\n" -E "$cert_pem_file":"$cert_password" \
-X POST \
-H "Accept: text/turtle" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "package-uri=${package_uri}" \
"${final_url}"
87 changes: 53 additions & 34 deletions config/system.trig
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,59 @@

# root admin

<urn:linkeddatahub:apps/admin> a lapp:Application, lapp:AdminApplication ;
dct:title "LinkedDataHub admin" ;
# ldt:base <https://admin.localhost:4443/> ;
ldh:origin <https://admin.localhost:4443> ;
ldt:ontology <https://w3id.org/atomgraph/linkeddatahub/admin#> ;
ldt:service <urn:linkeddatahub:services/admin> ;
ac:stylesheet <static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/layout.xsl> ;
lapp:endUserApplication <urn:linkeddatahub:apps/end-user> ;
lapp:frontendProxy <http://varnish-frontend:6060/> .

<urn:linkeddatahub:services/admin> a sd:Service ;
dct:title "LinkedDataHub admin service" ;
sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ;
sd:endpoint <http://fuseki-admin:3030/ds/> ;
a:graphStore <http://fuseki-admin:3030/ds/> ;
a:quadStore <http://fuseki-admin:3030/ds/> ;
lapp:backendProxy <http://varnish-admin/> .
<urn:linkeddatahub:apps/admin>
{
<urn:linkeddatahub:apps/admin> a lapp:Application, lapp:AdminApplication ;
dct:title "LinkedDataHub admin" ;
# ldt:base <https://admin.localhost:4443/> ;
lapp:origin <https://admin.localhost:4443> ;
ldt:ontology <https://w3id.org/atomgraph/linkeddatahub/admin#> ;
ldt:service <urn:linkeddatahub:services/admin> ;
ac:stylesheet <static/xsl/admin/layout.xsl> ;
lapp:endUserApplication <urn:linkeddatahub:apps/end-user> ;
lapp:frontendProxy <http://varnish-frontend:6060/> .

}

<urn:linkeddatahub:services/admin>
{

<urn:linkeddatahub:services/admin> a sd:Service ;
dct:title "LinkedDataHub admin service" ;
sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ;
sd:endpoint <http://fuseki-admin:3030/ds/> ;
a:graphStore <http://fuseki-admin:3030/ds/> ;
a:quadStore <http://fuseki-admin:3030/ds/> ;
lapp:backendProxy <http://varnish-admin/> .

}

# root end-user

<urn:linkeddatahub:apps/end-user> a lapp:Application, lapp:EndUserApplication ;
dct:title "LinkedDataHub" ;
# ldt:base <https://localhost:4443/> ;
ldh:origin <https://localhost:4443> ;
ldt:ontology <https://localhost:4443/ns#> ;
ldt:service <urn:linkeddatahub:services/end-user> ;
lapp:adminApplication <urn:linkeddatahub:apps/admin> ;
lapp:frontendProxy <http://varnish-frontend:6060/> ;
lapp:public true .

<urn:linkeddatahub:services/end-user> a sd:Service ;
dct:title "LinkedDataHub service" ;
sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ;
sd:endpoint <http://fuseki-end-user:3030/ds/> ;
a:graphStore <http://fuseki-end-user:3030/ds/> ;
a:quadStore <http://fuseki-end-user:3030/ds/> ;
lapp:backendProxy <http://varnish-end-user/> .
<urn:linkeddatahub:apps/end-user>
{
<urn:linkeddatahub:apps/end-user> a lapp:Application, lapp:EndUserApplication ;
dct:title "LinkedDataHub" ;
# ldt:base <https://localhost:4443/> ;
lapp:origin <https://localhost:4443> ;
ldt:ontology <https://localhost:4443/ns#> ;
ldt:service <urn:linkeddatahub:services/end-user> ;
ac:stylesheet <static/xsl/layout.xsl> ;
lapp:adminApplication <urn:linkeddatahub:apps/admin> ;
lapp:frontendProxy <http://varnish-frontend:6060/> ;
lapp:public true .

}

<urn:linkeddatahub:services/end-user>
{

<urn:linkeddatahub:services/end-user> a sd:Service ;
dct:title "LinkedDataHub service" ;
sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ;
sd:endpoint <http://fuseki-end-user:3030/ds/> ;
a:graphStore <http://fuseki-end-user:3030/ds/> ;
a:quadStore <http://fuseki-end-user:3030/ds/> ;
lapp:backendProxy <http://varnish-end-user/> .

}
Loading