Skip to content

Shakey-Bridge-Software/gs1-resolver

Repository files navigation

gs1-resolver

An open-source GS1 Digital Link conformant resolver, written in Clojure. Passes all 18 conformance criteria of the GS1-Conformant resolver standard v1.2.0 and scores 31/31 against the official browser-based test suite.

What this is

A reference implementation for people who want a working, spec-conformant GS1 DL resolver they can read, run, and extend. In-memory store, no database, no external service dependencies at runtime. The codebase is small enough to read in one sitting.

Status

  • 18 deftests covering each conformance criterion (58 assertions)
  • 31/31 on the upstream GS1 test suite, driven from headless Chromium
  • Continuous integration runs both suites on every push

Out of scope for this version:

  • Full GS1 Digital Link Compression decoder (a stub lookup table is in place)
  • Persistence beyond an in-memory atom

Architecture

gs1.resolver.path      ;; pure path-segment helpers
gs1.resolver.store     ;; in-memory atom + put!/get-record
gs1.resolver.fixtures  ;; conformance seed data
gs1.resolver.parse     ;; DL URI validation + GS1 AI vocabulary
gs1.resolver.linkset   ;; RFC 9264 linkset builder (pure)
gs1.resolver.handler   ;; Ring handler — orchestrates the above
gs1.resolver.server    ;; Jetty entry point (HTTP + optional HTTPS)

Dependencies flow one way. Linkset is a pure function of records, not a function that reaches into the store. The handler does the lookup.

Running it

Requirements: Java 21+, Clojure CLI.

HTTP only

clojure -M:run
# starts on http://localhost:8080

The server seeds a single GTIN (09506000164908) with five link types so you can probe the conformance behaviour immediately:

curl -i http://localhost:8080/01/09506000164908
curl -i 'http://localhost:8080/01/09506000164908?linkType=linkset'
curl -i 'http://localhost:8080/01/09506000164908?linkType=gs1:certificationInfo'
curl -i http://localhost:8080/.well-known/gs1resolver

HTTPS

The conformance suite expects HTTPS. Generate a self-signed keystore once:

./scripts/gen-keystore.sh

Then run with TLS:

SSL_PORT=8443 clojure -M:run
# starts on http://localhost:8080 and https://localhost:8443

Environment variables: PORT (default 8080), SSL_PORT (no default — HTTPS off unless set), KEYSTORE (default resources/keystore.jks), KEY_PASSWORD (default changeit).

Running the tests

Clojure unit/conformance tests

clojure -X:test

Official GS1 test suite (headless Chromium)

Drives the upstream JavaScript suite against your running resolver.

# one-time setup
npm install
npx playwright install chromium
sudo npx playwright install-deps chromium    # Linux only
./scripts/fetch-harness.sh    # download upstream GS1 suite assets
./scripts/gen-keystore.sh

# in one terminal
SSL_PORT=8443 clojure -M:run

# in another
node run-conformance.mjs

The runner boots a tiny static server for the harness page, intercepts the suite's calls to tester.php via Playwright's page.route (emulating the upstream PHP cURL helper with Node fetch), waits until the suite's result list stops growing, then prints a pass/fail summary.

Adding records

Edit src/gs1/resolver/fixtures.clj. Each record looks like:

{"/01/09506000164908"
 {:item-description  "Crew neck white t-shirt"
  :default-link-type "gs1:pip"
  :links
  {"gs1:pip"
   [{:href "https://example.com/pip"
     :title "Product Info"
     :type "text/html"
     :hreflang ["en"]}]
   "gs1:certificationInfo" [...]}}}

Anchor paths follow the canonical GS1 DL form: /01/{gtin} for primary, /01/{gtin}/21/{serial} for a serial-number qualifier, etc. The :default-link-type MUST exist as a key in :links.

REPL

clojure -M:nrepl
# nREPL on port 1667 with CIDER middleware

Upstream harness assets

The conformance harness loads three unmodified files from the GS1 test suite plus an Ajv bundle. They live in harness/ at runtime but are not committed — scripts/fetch-harness.sh downloads them, pinned to known commit SHAs and verified by checksum. To refresh against a newer upstream, update the SHAs at the top of the script, re-run it, and copy the printed checksums into the script's EXPECTED_ table.

Contributing

Issues and pull requests welcome. Before opening a PR:

  • clojure -X:test passes
  • node run-conformance.mjs returns 31/31 (or document a regression)

License

Apache License 2.0 — see LICENSE.

Third-party vendored components in harness/ are credited in NOTICE.

About

An open-source GS1 Digital Link conformant resolver, written in Clojure.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors