├── .github ├── ISSUE_TEMPLATE │ ├── challenge.md │ └── scenario.md └── workflows │ └── request-update-ongoing-challenges.yml ├── .gitignore ├── .markdownlint-cli2.cjs ├── README.md ├── how-to-manage-issues.md ├── package-lock.json ├── package.json ├── reports ├── README.md ├── agent-that-syncs-pods-and-google-sheets.md ├── aggregators-to-improve-social-media-data-access-across-many-pods.md ├── app-that-lists-apps-and-tooling.md ├── automatically-test-performance-of-each-css-commit.md ├── browser-extension-intercepting-urls-to-open-resources-with-user-defined-app.md ├── building-rendering-viewing-forms.md ├── determining-query-equivalence-between-newly-registered-query-and-already-executing-query.md ├── drag-drop-form-builder-to-build-basic-rdf-form-definition.md ├── edit-pod-files-in-vs-code.md ├── external-service-stores-calendar-in-pod.md ├── form-renderer-to-view-form-store-data.md ├── generic-query-based-data-viewer.md ├── greet-user-with-their-preferred-name.md ├── img │ ├── acmeplugin.png │ ├── form-renderer.png │ ├── from-generator.png │ ├── google-sheet-sync-sequence-diagram.png │ ├── lit-solid-login.png │ ├── location-history │ │ ├── approve-location-sharing.png │ │ ├── fetch-friends-location.png │ │ ├── request-friends-location.png │ │ ├── revoke-location-sharing.png │ │ └── set-up-location capture.png │ ├── perf-test-server.png │ ├── solid-app-store.png │ └── solid-menubar-app.png ├── menubar-app-to-check-who-is-on-vacation.md ├── mermaid │ └── agent-that-syncs-pods-and-google-sheets-diagram.txt ├── orchestrator-to-forward-ldn-notifications-to-inbox-based-on-n3-rules.md ├── public-css-instance-for-testing.md ├── read-and-write-data-in-web-app-relying-on-solid-authentication-browser-extension.md ├── store-manage-share-and-query-location-history-data.md ├── storing-large-real-time-data-streams-in-pod-using-LDES.md ├── template.md ├── temporal-usage-control-policy-execution-for-solid-resources.md └── web-component-for-solid-oidc-login.md ├── use-case-flow.jpg ├── use-case-flow.md └── use-case-flow.txt /.github/ISSUE_TEMPLATE/challenge.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Challenge 3 | about: A concrete technical problem applied to a specific use case 4 | title: '' 5 | labels: ['proposal: pending ❓', 'challenge'] 6 | assignees: 'RubenVerborgh' 7 | --- 8 | 14 | 15 | ## Pitch 16 | 26 | 27 | ## Desired solution 28 | 37 | 38 | ## Acceptance criteria 39 | 51 | 52 | ## Pointers 53 | 60 | 61 | ## Scenarios 62 | 69 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/scenario.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Scenario 3 | about: A flow of steps demonstrating a part of a use case 4 | title: '' 5 | labels: ['proposal: pending ❓', 'scenario'] 6 | assignees: 'RubenVerborgh' 7 | --- 8 | 14 | 15 | ## Actors/actresses 16 | 22 | 23 | ## Preconditions 24 | 31 | 32 | ## Steps 33 | 43 | 44 | ## Postconditions 45 | 52 | -------------------------------------------------------------------------------- /.github/workflows/request-update-ongoing-challenges.yml: -------------------------------------------------------------------------------- 1 | name: Check for ongoing challenges without updates 2 | on: 3 | schedule: 4 | - cron: '30 1 * * *' 5 | 6 | permissions: 7 | issues: write 8 | 9 | jobs: 10 | stale: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/stale@v4 14 | with: 15 | days-before-stale: 15 16 | days-before-close: -1 17 | only-labels: challenge,ongoing 18 | stale-issue-label: update-required 19 | stale-issue-message: 'Please provide a status update about this challenge. Every ongoing challenge needs at least one status update every 2 weeks. Thanks!' 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.markdownlint-cli2.cjs: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = { 4 | ignores: [ "node_modules/", "LICENSE.md", ".github/" ], 5 | 6 | globs: [ "**/*.md" ], 7 | 8 | config: { 9 | // Enable all markdownlint rules 10 | default: true, 11 | 12 | MD004: { 13 | "style": "dash" 14 | }, 15 | 16 | // Set list indent level to 2 17 | MD007: { "indent": 2 }, 18 | 19 | // Enable line length check but exclude tables and code blocks 20 | MD013: { 21 | line_length: 120, 22 | tables: false, 23 | code_blocks: false 24 | }, 25 | 26 | // Allow multiple subheadings with the same content 27 | // across different section (#1 ##A ##B #2 ##A ##B) 28 | MD024: { 29 | allow_different_nesting: true 30 | }, 31 | 32 | // Set Ordered list item prefix to "ordered" (use 1. 2. 3. not 1. 1. 1.) 33 | MD029: { "style": "ordered" }, 34 | 35 | // Allow inline HTML 36 | MD033: false, 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SolidLab Challenges 2 | 3 | This repository contains challenges that can be tackled during SolidLab. 4 | Each challenge is represented by a separate issue. 5 | Everybody is free to add new challenges using the provided template that you select when creating a new issue. 6 | This template helps you with providing the needed information for a challenge. 7 | 8 | **Please read all [instructions](./how-to-manage-issues.md) on how to manage challenges.** 9 | 10 | The Working Group 1 (Use Cases) of the Outreach component of SolidLab will create different use cases. 11 | You find the steps that you need to follow to turn these use cases into challenges via scenarios [here](use-case-flow.md). 12 | 13 | Once a scenario or challenge is completed, 14 | we write a report. 15 | You find all reports [here](reports). 16 | 17 | ## Useful links 18 | 19 | - Find all approved challenges without a lead 20 | [here](https://github.com/SolidLabResearch/Challenges/issues?q=is%3Aissue+is%3Aopen+no%3Aassignee+label%3A%22proposal%3A+approved+%E2%9C%85%22+label%3Achallenge). 21 | - Find all challenges that need changes and without assignee 22 | [here](https://github.com/SolidLabResearch/Challenges/issues?q=is%3Aissue+is%3Aopen+no%3Aassignee+label%3A%22proposal%3A+changes+needed+%F0%9F%91%B7%22+label%3Achallenge+). 23 | - Find all ongoing challenges 24 | [here](https://github.com/SolidLabResearch/Challenges/issues?q=is%3Aissue+is%3Aopen+label%3Achallenge+label%3Aongoing). 25 | - Find all challenges that await completion approval 26 | [here](https://github.com/SolidLabResearch/Challenges/issues?q=is%3Aissue+is%3Aopen+label%3A%22completion%3A+pending+%E2%9D%93%22+label%3A%22challenge%22). 27 | - Find all completed challenges 28 | [here](https://github.com/SolidLabResearch/Challenges/issues?q=is%3Aissue+is%3Aclosed+label%3A%22completion%3A+approved+%E2%9C%85%22). 29 | - Find all completed challenges without a report 30 | [here](https://github.com/SolidLabResearch/Challenges/issues?q=is%3Aissue+label%3A%22report%3A+ongoing+%F0%9F%91%B7%E2%80%8D%E2%99%82%EF%B8%8F%22). 31 | 32 | ## Lint markdown 33 | 34 | We use a linter to make sure that the markdown is correctly and consistently formatted. 35 | Follow these steps to run the linter: 36 | 37 | 1. Install dependencies via 38 | 39 | ```shell 40 | npm i 41 | ``` 42 | 43 | 2. Run the linter via 44 | 45 | ```shell 46 | npm run lint 47 | ``` 48 | 49 | We can fix some errors automatically via 50 | 51 | ```shell 52 | npm run lint:fix 53 | ``` 54 | -------------------------------------------------------------------------------- /how-to-manage-issues.md: -------------------------------------------------------------------------------- 1 | # How to manage issues 2 | 3 | ## New scenarios and challenges 4 | 5 | Every new scenario and challenge gets the label "proposal: pending ❓" and 6 | is assigned to Ruben Verborgh. 7 | He checks if the scenario/challenge is explained well-enough and 8 | if all need information is present. 9 | If everything is ok, the scenario/challenge gets the label "proposal: approved ✅", else 10 | it gets the label "proposal: changes needed 👷" and changes are needed. 11 | 12 | Once a challenge is approved Pieter Heyvaert looks for a lead for the challenge. 13 | 14 | ## Before starting challenge 15 | 16 | - When developing a Solid Web app, 17 | consider using our [template](https://github.com/SolidLabResearch/solid-web-app-template). 18 | If you don't use this template, let us know why 19 | (see section "Requirements before requesting completion approval of challenge" below). 20 | 21 | ## Updates on ongoing challenges 22 | 23 | Challenges that have a lead assigned require a status update via the issue every 2 weeks. 24 | 25 | ## Requirements before requesting completion approval of challenge 26 | 27 | Verify the following requirements before requesting the completion approval of your challenge: 28 | 29 | - The code/library/demo of the challenge must meet all acceptance criteria. 30 | - The code/library/demo must work with the Community Solid Server (CSS). 31 | CSS follows the Solid protocol so whatever the challenge produces as output must work with CSS. 32 | - You must provide copy-paste instructions to showcase the output of the challenge. 33 | You find an example [here](https://github.com/maartyman/solidBenchAggregatorDemo). 34 | - If the output of a challenge is a graphical user interface, such as a Web app or desktop app, 35 | then you have to provide a screencast of a flow demonstrating the acceptance criteria. 36 | The screencast needs to have audio explaining what is happening. 37 | - You must provide a list of important technical decisions and assumptions that were made, 38 | such as the shape and the location of data. 39 | - You must provide conclusions/actions that result from doing this challenge. 40 | For example, mention an unclarity in a specification, 41 | the need for a new function in a used library, 42 | a new challenge, or 43 | other future work. 44 | - You must provide the lessons you learned as a Solid developer, if any. 45 | These can be issues you encountered, tasks that could be automated or could be made easier and so on. 46 | - If you developed a Solid Web app, 47 | but didn't use our [template](https://github.com/SolidLabResearch/solid-web-app-template), 48 | you must let us know why. 49 | - You must create a 50 | [GitHub release](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository) 51 | for your solution. 52 | 53 | ## Completed scenarios and challenges 54 | 55 | Every scenario and challenge that you consider completed 56 | you assign the label "completion: pending ❓" and 57 | you assign the issue to Ruben Verborgh. 58 | You unassign the others. 59 | He checks the following: 60 | 61 | - If the aforementioned requirements are met. 62 | - If there is code of your solution that can be reused in the future. 63 | - If there are future work and actions that come from this challenge or its solution. 64 | 65 | If everything is ok, the scenario/challenge gets the labels "completion: approved ✅" and "report: ongoing 👷", else 66 | it gets the label "completion: changes needed 👷" and changes are needed. 67 | 68 | Once a challenge is approved three things happen: 69 | 70 | - Pieter Heyvaert creates a new issue in the repo [SolidLabLib.js](https://github.com/SolidLabResearch/SolidLabLib.js) 71 | for the reusable code, if any. 72 | - The person who created the code of the challenge has to add this code to this library. 73 | There are requirements for adding code such as tests and documentation. 74 | Please check with Ruben Taelman for details. 75 | He has ownership of this library. 76 | - Pieter Heyvaert writes a report as explained in the next section. 77 | 78 | ## Report 79 | 80 | Once a challenge is completed Pieter Heyvaert writes a report using [this template](reports/template.md). 81 | The person who reviewed the solution of the challenge also reviews the report. 82 | Once the report is done, Pieter adds label "report: done ✅" to the issue and closes it. 83 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Challenges", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "devDependencies": { 8 | "markdownlint-cli2": "^0.8.1" 9 | } 10 | }, 11 | "node_modules/@nodelib/fs.scandir": { 12 | "version": "2.1.5", 13 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 14 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 15 | "dev": true, 16 | "dependencies": { 17 | "@nodelib/fs.stat": "2.0.5", 18 | "run-parallel": "^1.1.9" 19 | }, 20 | "engines": { 21 | "node": ">= 8" 22 | } 23 | }, 24 | "node_modules/@nodelib/fs.stat": { 25 | "version": "2.0.5", 26 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 27 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 28 | "dev": true, 29 | "engines": { 30 | "node": ">= 8" 31 | } 32 | }, 33 | "node_modules/@nodelib/fs.walk": { 34 | "version": "1.2.8", 35 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 36 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 37 | "dev": true, 38 | "dependencies": { 39 | "@nodelib/fs.scandir": "2.1.5", 40 | "fastq": "^1.6.0" 41 | }, 42 | "engines": { 43 | "node": ">= 8" 44 | } 45 | }, 46 | "node_modules/argparse": { 47 | "version": "2.0.1", 48 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 49 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 50 | "dev": true 51 | }, 52 | "node_modules/braces": { 53 | "version": "3.0.2", 54 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 55 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 56 | "dev": true, 57 | "dependencies": { 58 | "fill-range": "^7.0.1" 59 | }, 60 | "engines": { 61 | "node": ">=8" 62 | } 63 | }, 64 | "node_modules/dir-glob": { 65 | "version": "3.0.1", 66 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 67 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 68 | "dev": true, 69 | "dependencies": { 70 | "path-type": "^4.0.0" 71 | }, 72 | "engines": { 73 | "node": ">=8" 74 | } 75 | }, 76 | "node_modules/entities": { 77 | "version": "3.0.1", 78 | "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", 79 | "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", 80 | "dev": true, 81 | "engines": { 82 | "node": ">=0.12" 83 | }, 84 | "funding": { 85 | "url": "https://github.com/fb55/entities?sponsor=1" 86 | } 87 | }, 88 | "node_modules/fast-glob": { 89 | "version": "3.3.1", 90 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", 91 | "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", 92 | "dev": true, 93 | "dependencies": { 94 | "@nodelib/fs.stat": "^2.0.2", 95 | "@nodelib/fs.walk": "^1.2.3", 96 | "glob-parent": "^5.1.2", 97 | "merge2": "^1.3.0", 98 | "micromatch": "^4.0.4" 99 | }, 100 | "engines": { 101 | "node": ">=8.6.0" 102 | } 103 | }, 104 | "node_modules/fastq": { 105 | "version": "1.15.0", 106 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", 107 | "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", 108 | "dev": true, 109 | "dependencies": { 110 | "reusify": "^1.0.4" 111 | } 112 | }, 113 | "node_modules/fill-range": { 114 | "version": "7.0.1", 115 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 116 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 117 | "dev": true, 118 | "dependencies": { 119 | "to-regex-range": "^5.0.1" 120 | }, 121 | "engines": { 122 | "node": ">=8" 123 | } 124 | }, 125 | "node_modules/glob-parent": { 126 | "version": "5.1.2", 127 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 128 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 129 | "dev": true, 130 | "dependencies": { 131 | "is-glob": "^4.0.1" 132 | }, 133 | "engines": { 134 | "node": ">= 6" 135 | } 136 | }, 137 | "node_modules/globby": { 138 | "version": "13.1.4", 139 | "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", 140 | "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", 141 | "dev": true, 142 | "dependencies": { 143 | "dir-glob": "^3.0.1", 144 | "fast-glob": "^3.2.11", 145 | "ignore": "^5.2.0", 146 | "merge2": "^1.4.1", 147 | "slash": "^4.0.0" 148 | }, 149 | "engines": { 150 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 151 | }, 152 | "funding": { 153 | "url": "https://github.com/sponsors/sindresorhus" 154 | } 155 | }, 156 | "node_modules/ignore": { 157 | "version": "5.2.4", 158 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", 159 | "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", 160 | "dev": true, 161 | "engines": { 162 | "node": ">= 4" 163 | } 164 | }, 165 | "node_modules/is-extglob": { 166 | "version": "2.1.1", 167 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 168 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 169 | "dev": true, 170 | "engines": { 171 | "node": ">=0.10.0" 172 | } 173 | }, 174 | "node_modules/is-glob": { 175 | "version": "4.0.3", 176 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 177 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 178 | "dev": true, 179 | "dependencies": { 180 | "is-extglob": "^2.1.1" 181 | }, 182 | "engines": { 183 | "node": ">=0.10.0" 184 | } 185 | }, 186 | "node_modules/is-number": { 187 | "version": "7.0.0", 188 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 189 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 190 | "dev": true, 191 | "engines": { 192 | "node": ">=0.12.0" 193 | } 194 | }, 195 | "node_modules/linkify-it": { 196 | "version": "4.0.1", 197 | "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", 198 | "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", 199 | "dev": true, 200 | "dependencies": { 201 | "uc.micro": "^1.0.1" 202 | } 203 | }, 204 | "node_modules/markdown-it": { 205 | "version": "13.0.1", 206 | "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", 207 | "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", 208 | "dev": true, 209 | "dependencies": { 210 | "argparse": "^2.0.1", 211 | "entities": "~3.0.1", 212 | "linkify-it": "^4.0.1", 213 | "mdurl": "^1.0.1", 214 | "uc.micro": "^1.0.5" 215 | }, 216 | "bin": { 217 | "markdown-it": "bin/markdown-it.js" 218 | } 219 | }, 220 | "node_modules/markdownlint": { 221 | "version": "0.29.0", 222 | "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.29.0.tgz", 223 | "integrity": "sha512-ASAzqpODstu/Qsk0xW5BPgWnK/qjpBQ4e7IpsSvvFXcfYIjanLTdwFRJK1SIEEh0fGSMKXcJf/qhaZYHyME0wA==", 224 | "dev": true, 225 | "dependencies": { 226 | "markdown-it": "13.0.1", 227 | "markdownlint-micromark": "0.1.5" 228 | }, 229 | "engines": { 230 | "node": ">=16" 231 | } 232 | }, 233 | "node_modules/markdownlint-cli2": { 234 | "version": "0.8.1", 235 | "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.8.1.tgz", 236 | "integrity": "sha512-y0Siwt+RApKxSSb0CT9p7z1DcAO+ncjrB9IpC/jflJRIet4namCFmxLTbfBBQdPF6EntPk5yyXKe7vcoPGlnXw==", 237 | "dev": true, 238 | "dependencies": { 239 | "globby": "13.1.4", 240 | "markdownlint": "0.29.0", 241 | "markdownlint-cli2-formatter-default": "0.0.4", 242 | "micromatch": "4.0.5", 243 | "strip-json-comments": "5.0.0", 244 | "yaml": "2.3.1" 245 | }, 246 | "bin": { 247 | "markdownlint-cli2": "markdownlint-cli2.js", 248 | "markdownlint-cli2-config": "markdownlint-cli2-config.js", 249 | "markdownlint-cli2-fix": "markdownlint-cli2-fix.js" 250 | }, 251 | "engines": { 252 | "node": ">=16" 253 | } 254 | }, 255 | "node_modules/markdownlint-cli2-formatter-default": { 256 | "version": "0.0.4", 257 | "resolved": "https://registry.npmjs.org/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.4.tgz", 258 | "integrity": "sha512-xm2rM0E+sWgjpPn1EesPXx5hIyrN2ddUnUwnbCsD/ONxYtw3PX6LydvdH6dciWAoFDpwzbHM1TO7uHfcMd6IYg==", 259 | "dev": true, 260 | "peerDependencies": { 261 | "markdownlint-cli2": ">=0.0.4" 262 | } 263 | }, 264 | "node_modules/markdownlint-micromark": { 265 | "version": "0.1.5", 266 | "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.5.tgz", 267 | "integrity": "sha512-HvofNU4QCvfUCWnocQP1IAWaqop5wpWrB0mKB6SSh0fcpV0PdmQNS6tdUuFew1utpYlUvYYzz84oDkrD76GB9A==", 268 | "dev": true, 269 | "engines": { 270 | "node": ">=16" 271 | } 272 | }, 273 | "node_modules/mdurl": { 274 | "version": "1.0.1", 275 | "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", 276 | "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", 277 | "dev": true 278 | }, 279 | "node_modules/merge2": { 280 | "version": "1.4.1", 281 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 282 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 283 | "dev": true, 284 | "engines": { 285 | "node": ">= 8" 286 | } 287 | }, 288 | "node_modules/micromatch": { 289 | "version": "4.0.5", 290 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", 291 | "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", 292 | "dev": true, 293 | "dependencies": { 294 | "braces": "^3.0.2", 295 | "picomatch": "^2.3.1" 296 | }, 297 | "engines": { 298 | "node": ">=8.6" 299 | } 300 | }, 301 | "node_modules/path-type": { 302 | "version": "4.0.0", 303 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 304 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 305 | "dev": true, 306 | "engines": { 307 | "node": ">=8" 308 | } 309 | }, 310 | "node_modules/picomatch": { 311 | "version": "2.3.1", 312 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 313 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 314 | "dev": true, 315 | "engines": { 316 | "node": ">=8.6" 317 | }, 318 | "funding": { 319 | "url": "https://github.com/sponsors/jonschlinkert" 320 | } 321 | }, 322 | "node_modules/queue-microtask": { 323 | "version": "1.2.3", 324 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 325 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 326 | "dev": true, 327 | "funding": [ 328 | { 329 | "type": "github", 330 | "url": "https://github.com/sponsors/feross" 331 | }, 332 | { 333 | "type": "patreon", 334 | "url": "https://www.patreon.com/feross" 335 | }, 336 | { 337 | "type": "consulting", 338 | "url": "https://feross.org/support" 339 | } 340 | ] 341 | }, 342 | "node_modules/reusify": { 343 | "version": "1.0.4", 344 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 345 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 346 | "dev": true, 347 | "engines": { 348 | "iojs": ">=1.0.0", 349 | "node": ">=0.10.0" 350 | } 351 | }, 352 | "node_modules/run-parallel": { 353 | "version": "1.2.0", 354 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 355 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 356 | "dev": true, 357 | "funding": [ 358 | { 359 | "type": "github", 360 | "url": "https://github.com/sponsors/feross" 361 | }, 362 | { 363 | "type": "patreon", 364 | "url": "https://www.patreon.com/feross" 365 | }, 366 | { 367 | "type": "consulting", 368 | "url": "https://feross.org/support" 369 | } 370 | ], 371 | "dependencies": { 372 | "queue-microtask": "^1.2.2" 373 | } 374 | }, 375 | "node_modules/slash": { 376 | "version": "4.0.0", 377 | "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", 378 | "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", 379 | "dev": true, 380 | "engines": { 381 | "node": ">=12" 382 | }, 383 | "funding": { 384 | "url": "https://github.com/sponsors/sindresorhus" 385 | } 386 | }, 387 | "node_modules/strip-json-comments": { 388 | "version": "5.0.0", 389 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.0.tgz", 390 | "integrity": "sha512-V1LGY4UUo0jgwC+ELQ2BNWfPa17TIuwBLg+j1AA/9RPzKINl1lhxVEu2r+ZTTO8aetIsUzE5Qj6LMSBkoGYKKw==", 391 | "dev": true, 392 | "engines": { 393 | "node": ">=14.16" 394 | }, 395 | "funding": { 396 | "url": "https://github.com/sponsors/sindresorhus" 397 | } 398 | }, 399 | "node_modules/to-regex-range": { 400 | "version": "5.0.1", 401 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 402 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 403 | "dev": true, 404 | "dependencies": { 405 | "is-number": "^7.0.0" 406 | }, 407 | "engines": { 408 | "node": ">=8.0" 409 | } 410 | }, 411 | "node_modules/uc.micro": { 412 | "version": "1.0.6", 413 | "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", 414 | "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", 415 | "dev": true 416 | }, 417 | "node_modules/yaml": { 418 | "version": "2.3.1", 419 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", 420 | "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", 421 | "dev": true, 422 | "engines": { 423 | "node": ">= 14" 424 | } 425 | } 426 | } 427 | } 428 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "lint": "markdownlint-cli2", 4 | "lint:fix": "markdownlint-cli2-fix" 5 | }, 6 | "devDependencies": { 7 | "markdownlint-cli2": "^0.8.1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /reports/README.md: -------------------------------------------------------------------------------- 1 | # Reports 2 | 3 | Once a scenario or challenge is completed, we write a report. 4 | You find the template [here](template.md). 5 | 6 | ## All reports 7 | 8 | - [Agent that syncs pods and Google Sheets](./agent-that-syncs-pods-and-google-sheets.md) 9 | - [Aggregators to improve social media data access across many pods](./aggregators-to-improve-social-media-data-access-across-many-pods.md) 10 | - [App that lists apps and tooling](./app-that-lists-apps-and-tooling.md) 11 | - [Automatically test performance of each CSS commit](./automatically-test-performance-of-each-css-commit.md) 12 | - [Browser extension intercepting urls to open resources with user-defined app](./browser-extension-intercepting-urls-to-open-resources-with-user-defined-app.md) 13 | - [Building, rendering, and viewing forms](./building-rendering-viewing-forms.md) 14 | - [Determining query equivalence between newly registered query and already executing query](./determining-query-equivalence-between-newly-registered-query-and-already-executing-query.md) 15 | - [Drag & drop form builder to build basic RDF form definition](./drag-drop-form-builder-to-build-basic-rdf-form-definition.md) 16 | - [Edit pod files in Visual Studio Code](./edit-pod-files-in-vs-code.md) 17 | - [External service stores calendar in pod](./external-service-stores-calendar-in-pod.md) 18 | - [Form renderer that to view RDF form and store filled-in data in pod](./form-renderer-to-view-form-store-data.md) 19 | - [Generic query-based data viewer](./generic-query-based-data-viewer.md) 20 | - [Greet user with preferred name](./greet-user-with-their-preferred-name.md) 21 | - [Menubar app to check who is on vacation](./menubar-app-to-check-who-is-on-vacation.md) 22 | - [Orchestrator to forward LDN notifications to LDN inbox based on N3 rules](./orchestrator-to-forward-ldn-notifications-to-inbox-based-on-n3-rules.md) 23 | - [Public Community Solid Server instance for testing](./public-css-instance-for-testing.md) 24 | - [Read and write data in Web app relying on Solid authentication browser extension](./read-and-write-data-in-web-app-relying-on-solid-authentication-browser-extension.md) 25 | - [Store, manage, share and query location (history) data](./store-manage-share-and-query-location-history-data.md) 26 | - [Storing large real-time data streams in pod using LDES](./storing-large-real-time-data-streams-in-pod-using-LDES.md) 27 | - [Temporal Usage Control Policy execution for Solid Resources](./temporal-usage-control-policy-execution-for-solid-resources.md) 28 | - [Web Component for Solid-OIDC login](./web-component-for-solid-oidc-login.md) 29 | 30 | ## Reports with follow-up actions 31 | 32 | Below you find the reports with follow-up actions for 33 | the Community Solid Server, Comunica, SolidLabLib.js, or other libraries/tools. 34 | 35 | ### Community Solid Server 36 | 37 | None. 38 | 39 | ### Comunica 40 | 41 | None. 42 | 43 | ### SolidLabLib.js 44 | 45 | - [Greet user with preferred name](./greet-user-with-their-preferred-name.md) 46 | 47 | ### Other 48 | 49 | - [Agent that syncs pods and Google Sheets](./agent-that-syncs-pods-and-google-sheets.md) 50 | - [Automatically test performance of each CSS commit](./automatically-test-performance-of-each-css-commit.md) 51 | - [External service stores calendar in pod](./external-service-stores-calendar-in-pod.md) 52 | - [Generic query-based data viewer](./generic-query-based-data-viewer.md) 53 | - [Menubar app to check who is on vacation](./menubar-app-to-check-who-is-on-vacation.md) 54 | - [Temporal Usage Control Policy execution for Solid Resources](./temporal-usage-control-policy-execution-for-solid-resources.md) 55 | -------------------------------------------------------------------------------- /reports/agent-that-syncs-pods-and-google-sheets.md: -------------------------------------------------------------------------------- 1 | 15 | 16 | # Agent that syncs pods and Google Sheets 17 | 18 | The corresponding challenge is [#120](https://github.com/SolidLabResearch/Challenges/issues/120), 19 | which contributes to scenario [#119](https://github.com/SolidLabResearch/Challenges/issues/119). 20 | 21 | ## Problem 22 | 26 | 27 | A lot of users use Google Sheets to view and edit data. 28 | This data can be stored in Google Sheets itself or 29 | it can be coming from an external data source such as a 30 | [MySQL database](https://coefficient.io/how-to-connect-mysql-database-to-google-sheets) or 31 | [MongoDB](https://hightouch.com/integrations/google-sheets-source-to-mongodb). 32 | So far, there is no solution that exists that allows doing this with data in Solid pods. 33 | Challenge [#120](https://github.com/SolidLabResearch/Challenges/issues/120) 34 | focuses on the agent/backend part of a solution for this problem. 35 | 36 | ## Approved solution 37 | 41 | 42 | We created an [agent](https://github.com/SolidLabResearch/google-sheet-sync/releases/tag/v1.0.0) that 43 | syncs data between a Google Sheet and a resource on a Solid pod. 44 | It has the following features: 45 | 46 | - Users define which Google Sheet and resource the agent syncs. 47 | - Users define via a SPARQL query what data the agent selects from the resource. 48 | - Users define via YARRRML rules how the data from the sheet is converted to RDF before it is stored in the resource. 49 | - The agent overwrites the sheet with all the queried data when it launches. 50 | - The agent periodically checks the sheet for changes and stores these changes in the resource. 51 | - The agent only works with public resources. 52 | 53 | You find a screencast of the agent [here](https://cloud.ilabt.imec.be/index.php/s/eFrEKF2YCkSx22j). 54 | You find the details on how to configure the agent for your use case 55 | [here](https://github.com/SolidLabResearch/google-sheet-sync/tree/fac52cc087d999e8b3de465c4871f5e2ba06ab62#configuration). 56 | This includes how to use your own sheets, pods and queries. 57 | 58 | 61 | We made the following important technological decisions and assumptions: 62 | 63 | - We did not include Solid authentication in this agent 64 | because we have done authentication in other challenges, and 65 | it is not crucial for this challenge. 66 | [This](https://github.com/SolidLabResearch/google-sheet-sync/issues/13) is the corresponding issue to implement this. 67 | - We compare the RDF of the original data in the sheet with the RDF of the current data in the sheet to determine 68 | what triples needed to be added to and deleted from the resource. 69 | See this 70 | [part](https://github.com/SolidLabResearch/google-sheet-sync/blob/fac52cc087d999e8b3de465c4871f5e2ba06ab62/src/main.js#L171) 71 | of the code. 72 | - We use a public instance of the [RMLMapper Web API](https://github.com/RMLio/rmlmapper-webapi-js) to convert 73 | data from the sheet to RDF. 74 | It is possible to set up a local instance of this API if you don't want to use a public one. 75 | - We make use of the [googleapis](https://github.com/googleapis/google-api-nodejs-client) to interact with Google Sheets. 76 | But we did not find any open-source library that 77 | already does the two-way syncing of Google Sheets with another data source. 78 | And to which we could directly add support for Solid. 79 | We either found snippets that use the aforementioned library or 80 | commercial solutions that are not open source. 81 | - The agent needs access and refresh tokens to interact with Google Sheets on behalf of the user of the sheet. 82 | The agent reads these tokens from a JSON file. 83 | How the tokens are added to the JSON file is out of scope of the agent. 84 | Therefore, we provide an 85 | [authentication server](https://github.com/SolidLabResearch/google-sheet-sync/tree/fac52cc087d999e8b3de465c4871f5e2ba06ab62#oauth2-tokens). 86 | This server asks the user of the sheet to log in with their Google account and 87 | give access to the agent to make changes to Google Sheets. 88 | 89 | Below you find a sequence diagram of how the agent works with the resource and the Google Sheet. 90 | 91 | ![A sequence diagram of how the agent works. 92 | It has 2 actors: agent user and sheet user. 93 | It has 3 participants: sync agent, resource, Google Sheet. 94 | It has 12 steps, which are explained below in detail as well. 95 | ](./img/google-sheet-sync-sequence-diagram.png) 96 | 97 | The diagram has the following steps: 98 | 99 | 1. The user of the agent configures the agent via a config file. 100 | 2. The user of the agent starts the agent. 101 | 3. The agent queries the data from the resource on the pod. 102 | 4. The resource returns the data as RDF. 103 | 5. The agent converts the RDF to a 2D-array. 104 | 6. The agent fills the sheet with the data from the array. 105 | 7. The user of the sheet edits one or more fields. 106 | 8. Periodically the agent checks for changes. 107 | This starts with querying the data from the sheet. 108 | 9. The sheet returns the data. 109 | 10. The agent checks if there are changes on the data. 110 | 11. If there are changes, the agent converts the changes to RDF. 111 | 12. The agent writes the changes to the resource. 112 | 113 | ## User flow 114 | 115 | 119 | 120 | This user flow describes how to set up and show a demo of the agent. 121 | 122 | ### Actors/actresses 123 | 124 | - User of the agent. 125 | - User of the Google Sheet. 126 | - User of the pod. 127 | 128 | In the steps below we don't make a difference between the different users 129 | as these steps are only meant to demo the solution of the challenge. 130 | 131 | ### Preconditions 132 | 133 | - The users of the agent and pod have Node.js installed. 134 | - The user of the agent has set a Client ID and Secret for the Google API. 135 | See [these instructions](https://github.com/SolidLabResearch/google-sheet-sync#google-sheet-api). 136 | - The user of Google Sheet has a sheet that the agent can sync with. 137 | 138 | ### Steps 139 | 140 | 1. Clone the [repository](https://github.com/SolidLabResearch/google-sheet-sync/) (v1.0.0) via 141 | 142 | ```shell 143 | git clone -b v1.0.0 https://github.com/SolidLabResearch/google-sheet-sync.git 144 | ``` 145 | 146 | 2. Install the dependencies via 147 | 148 | ```shell 149 | npm i 150 | ``` 151 | 152 | 3. Start the authentication server that enables us to give access to a Google account via 153 | 154 | ```shell 155 | npm run auth 156 | ``` 157 | 158 | The server is ready when the following message appears in the terminal: 159 | 160 | ```text 161 | Authentication server running on port 8081 162 | ``` 163 | 164 | We will use this account to access the aforementioned Google Sheet. 165 | 4. Navigate to in the browser. 166 | 5. Click on the "Authenticate" button. 167 | 6. Log in with the Google account that has access to the aforementioned Google Sheet. 168 | 7. Click on "Continue" when you get the message "Google hasn't verified this app". 169 | 8. Click on "Continue" when you get the message "Sheet Solid sync wants access to your Google Account". 170 | 9. If the authentication succeeded, then you get the message "Authentication successful. Credentials written to credentials.json." 171 | 10. Stop the sever via CTRL + C. 172 | 11. Prepare the local instance of the Community Solid Server (CSS) via 173 | 174 | ```shell 175 | npm run prepare:pods 176 | ``` 177 | 178 | 12. Start the CSS instance via 179 | 180 | ```shell 181 | npm run start:pods 182 | ``` 183 | 184 | The agent will use the data in the resource . 185 | The CSS instance is ready when the following message appears in the terminal: 186 | 187 | ```text 188 | Listening to server at http://localhost:3000/ 189 | ``` 190 | 191 | 13. Open another terminal. 192 | 14. Copy the example config `config.query.example.yml` to `config.yml` via 193 | 194 | ```shell 195 | cp config.query.example.yml config.yml 196 | ``` 197 | 198 | 15. Set the `sheet.id` in `config.yml` to the ID of the Google Sheet. 199 | See [these instructions](https://github.com/SolidLabResearch/google-sheet-sync/tree/main#id-string). 200 | 16. Copy the example YARRRML rules `rules.example.yml` to `rules.yml` via 201 | 202 | ```shell 203 | cp rules.example.yml rules.yml 204 | ``` 205 | 206 | 17. Start the agent via 207 | 208 | ```shell 209 | npm start 210 | ``` 211 | 212 | 18. The agent has synced the data that is in the resource to 213 | the Google Sheet once the following message appears in the terminal: 214 | 215 | ```text 216 | Synchronisation cold start completed 217 | ``` 218 | 219 | 19. Verify that the data is in the Google Sheet. 220 | 20. Change a cell in the Google Sheet. 221 | 21. The agent will detect this change and update the resource. 222 | The update is done when the following message appears in the terminal: 223 | 224 | ```text 225 | Synchronization done. 226 | ``` 227 | 228 | 22. Verify that the agent updated the resource by browsing to . 229 | 230 | ### Postconditions 231 | 232 | None. 233 | 234 | ## Follow-up actions 235 | 239 | 240 | - Users can only define one resource 241 | because the agent can only store the changes from a Google Sheet in one resource. 242 | The agent should be able to support multiple resource. 243 | [This](https://github.com/SolidLabResearch/google-sheet-sync/issues/12) is the corresponding issue. 244 | 245 | ## Future work 246 | 251 | 252 | - Automatically determine the corresponding YARRRML rules for a SPARQL query. 253 | 254 | ## Lessons learned about developer experience 255 | 259 | 260 | None. 261 | -------------------------------------------------------------------------------- /reports/aggregators-to-improve-social-media-data-access-across-many-pods.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Aggregators to improve social media data access across many pods 15 | 16 | The corresponding challenge is [#24](https://github.com/SolidLabResearch/Challenges/issues/24). 17 | 18 | ## Problem 19 | 20 | Applications that require to aggregate data across many pods can be faced with slow response times due to 21 | the latency of data retrieval and processing of the large number of pods. 22 | This is typically the case in a social media scenario, 23 | where the timelines of their users are curated based on the activities of their contacts. 24 | Computing these timelines when the users access their social media applications is typically not feasible 25 | due to latency constraints. 26 | Therefore, the timelines should be precomputed as a form of aggregation. 27 | 28 | ## Approved solution 29 | 33 | 34 | We developed a [demo](https://github.com/maartyman/solidBenchAggregatorDemo) that 35 | uses our [Solid Aggregator Server](https://github.com/maartyman/solid-aggregator-server) and 36 | [Solid Aggregator Client](https://github.com/maartyman/solid-aggregator-client) 37 | to show the difference in execution time of a query 38 | between using the aggregator and not using the aggregator. 39 | We use the [SolidBench.js](https://github.com/SolidBench/SolidBench.js) benchmark to 40 | simulate data pods with social media data. 41 | 42 | The Solid Aggregator Server functions as an intermediate component in the Solid network. 43 | The server accepts queries from client applications and 44 | directly exposes the result of the queries, which are the computed bindings. 45 | This allows client applications to retrieve the query results directly from the aggregator instead of 46 | evaluating expensive queries themselves. 47 | The Solid Aggregator Client make it easier for developers to work with the aggregator. 48 | 49 | This server computes the bindings and 50 | keeps them up to date when changes in the resources in the Solid network occur. 51 | In other words, the server makes sure that changes in the resources are reflected in 52 | the resulting bindings of a specific query. 53 | We do this by re-evaluating the queries every time a resource has changed. 54 | 55 | ## User flow 56 | 57 | ### Actors/actresses 58 | 59 | - User of the demo 60 | 61 | ### Preconditions 62 | 63 | - The user has Node.js installed. 64 | 65 | ### Steps 66 | 67 | 1. Clone the [demo repo](https://github.com/maartyman/solidBenchAggregatorDemo) via `git clone https://github.com/maartyman/solidBenchAggregatorDemo.git`. 68 | 2. Install dependencies via `npm i`. 69 | 3. Set up and start servers via `npm run setupAndStartServers`. 70 | 4. Wait till the console says "Everything is set up and ready for the demo!". 71 | 5. Execute one of the four demo queries in a new terminal: 72 | - Find all the WebIDs of the friends of pod `00000000000000000933` via `npm run simple-query` 73 | (see [details](https://github.com/maartyman/solidBenchAggregatorDemo#demo-1)). 74 | - Determine the distance between user `00000000000000000102` and some predetermined users via `npm run complex-query` 75 | (see [details](https://github.com/maartyman/solidBenchAggregatorDemo#demo-2)). 76 | - Find all the posts in a pod (including where they were posted and their contents) via `npm run link-traversal-query` 77 | (see [details](https://github.com/maartyman/solidBenchAggregatorDemo#demo-3)). 78 | - Find all the WebId's of the friends of pod `00000000000000000933` while adding and removing a friend every 2 second 79 | via `npm run update-example` (see [details](https://github.com/maartyman/solidBenchAggregatorDemo#demo-4)). 80 | 81 | ### Postconditions 82 | 83 | The user sees the results of the query in the terminal where the query was started. 84 | For `npm run complex-query` that is 85 | 86 | ```text 87 | Result aggregated (0.005 s): 88 | bindings: 89 | fr: http://localhost:3000/pods/00000000000000000296/profile/card#me 90 | dist: 1 91 | bindings: 92 | fr: http://localhost:3000/pods/00000000000000000318/profile/card#me 93 | dist: 1 94 | ... 95 | Result client (46.363 s): 96 | bindings: 97 | fr: http://localhost:3000/pods/00000000000000000296/profile/card#me 98 | dist: 1 99 | bindings: 100 | fr: http://localhost:3000/pods/00000000000000000318/profile/card#me 101 | dist: 1 102 | ... 103 | ``` 104 | 105 | Using the aggregator it takes only 0.005s to get the results, while 106 | when executing the query solely in a client application it takes 46.363s. 107 | 108 | ## Follow-up actions 109 | 110 | - Instead of re-executing the query, use incremental approaches. 111 | - Use incremental link-traversal. 112 | - Use incremental schema-alignment. 113 | - Research discoverability of the aggregator and combining the result of multiple aggregators to get the results to a query. 114 | - Expose a SPARQL endpoint so that any SPARQL client can use it. 115 | 116 | ## Future work 117 | 118 | None. 119 | -------------------------------------------------------------------------------- /reports/app-that-lists-apps-and-tooling.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # App that lists apps and tooling 15 | 16 | The corresponding challenge is [#30](https://github.com/SolidLabResearch/Challenges/issues/30). 17 | 18 | ## Problem 19 | 20 | The goal is for the Solid project to "eat its own dog food" by having an app/interface in which users can see 21 | which apps and developer tooling exist within the ecosystem. 22 | 23 | Concretely: 24 | 25 | - There exists an ontology with which apps and tooling are described. 26 | - The data is published and maintained in a sustainable way. 27 | - Developers are incentivied to keep an up-to-date record of their work 28 | or this can be entirely automated for them by scraping data from 29 | wherever they are doing their work such as GitHub, Gitlab, and so on. 30 | 31 | In the long term, I would envision this to be an app store for Solid apps and a wiki for developer tooling/sdks. 32 | 33 | ## Approved solution 34 | 35 | We developed a [Web app](https://github.com/KNowledgeOnWebScale/solid-app-store/) that 36 | shows users a lists of apps and libraries. 37 | Users can filter on category and search on the names and descriptions of apps and libraries. 38 | There are also [shapes](https://github.com/KNowledgeOnWebScale/solid-app-store#how-to-add-app-to-store) 39 | for how information about the apps should be published. 40 | You find a live version of the app [here](https://solid-app-store.netlify.app/). 41 | 42 | Below you find a screenshot of the app. 43 | 44 | ![img.png](img/solid-app-store.png) 45 | 46 | ## User flow 47 | 48 | ### Actors/actresses 49 | 50 | - Web app 51 | - User of the application 52 | 53 | ### Preconditions 54 | 55 | None. 56 | 57 | ### Steps 58 | 59 | 1. The user opens the Web app. 60 | 2. The user searches for "editor". 61 | 62 | ### Postconditions 63 | 64 | - The app shows two apps: "solideditor" and "waceditor". 65 | 66 | ## Follow-up actions 67 | 68 | None. 69 | 70 | ## Future work 71 | 72 | - Users can set their own sources where the app store fetches the information about apps and libraries. 73 | Now this is hard-coded. 74 | -------------------------------------------------------------------------------- /reports/automatically-test-performance-of-each-css-commit.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Automatically test performance of each Community Solid Server commit 15 | 16 | The corresponding challenge is [#23](https://github.com/SolidLabResearch/Challenges/issues/23). 17 | 18 | ## Problem 19 | 20 | Changes to code of [Community Solid Server](https://github.com/CommunitySolidServer/CommunitySolidServer) (CSS) 21 | can have an impact on the memory, CPU and even bandwidth usage of the CSS. 22 | It would be nice to know this impact for each commit to the CSS repo, 23 | to spot performance impact as soon as possible. 24 | 25 | ## Approved solution 26 | 27 | We developed the [SolidLab Performance Test Server](https://github.com/SolidLabResearch/solidlab-perftest-server/). 28 | It offers both a backend and frontend. 29 | The frontend is available at . 30 | You find a screenshot of it below. 31 | You find more information about 32 | the architecture [here](https://github.com/SolidLabResearch/solidlab-perftest-server/blob/master/docs/architecture.md). 33 | 34 | ![Frontend of the server](img/perf-test-server.png) 35 | 36 | ## Follow-up actions 37 | 38 | - Improving the performance of the server. 39 | - Fixing bugs. 40 | 41 | ## Future work 42 | 43 | - Make the server usable for non-CSS tests. 44 | -------------------------------------------------------------------------------- /reports/browser-extension-intercepting-urls-to-open-resources-with-user-defined-app.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Browser extension intercepting urls to open resources with user-defined app 15 | 16 | The corresponding challenge is [#45](https://github.com/SolidLabResearch/Challenges/issues/45). 17 | 18 | ## Problem 19 | 20 | In a decentralized Solid world many applications will provide functionality to do one or more specialised actions, 21 | such as browsing files, playing games, creating a Doodle, participating in a Quiz. 22 | In this environment users have a preference for apps they want to use to do some tasks: 23 | 24 | - When the user wants to browse a pod, she wants to use App X. 25 | - When the user wants to play chess, she wants to use App Y. 26 | - When the user wants to edit a text resource, she wants to use App Z. 27 | 28 | ## Approved solution 29 | 30 | We developed a [browser extension](https://github.com/phochste/AcmePlugin) that 31 | allows users to open resources with existing Solid apps via the context menu. 32 | You can configure what Web pages and resources are considered by the extension and what specific apps should be used. 33 | Below you see a screenshot of the context menu that appears when right-clinking on a page 34 | when the plugin is installed. 35 | 36 | ![A context menu that appears when right-clicking on a page. 37 | It has the option "Acme Open in". 38 | This option has three options: edit, open, and permissions.](img/acmeplugin.png) 39 | 40 | ## User flow 41 | 42 | ### Actors/actresses 43 | 44 | - Browser extension 45 | - User of the extension 46 | 47 | ### Preconditions 48 | 49 | - The user has installed the extension in the browser. 50 | 51 | ### Steps 52 | 53 | 1. The user visits a Web page that is considered by the extension. 54 | 2. The user right-clicks on a resource that is considered by the extension. 55 | 3. The extension opens the corresponding Solid app and loads the resource. 56 | 57 | ### Postconditions 58 | 59 | - The resource is opened in the preferred Solid app based on the extension's configuration. 60 | 61 | ## Follow-up actions 62 | 63 | None. 64 | 65 | ## Future work 66 | 67 | - Advanced functions implementations might consider creating (N3) rules to decide what app to open based on resources/types. 68 | -------------------------------------------------------------------------------- /reports/building-rendering-viewing-forms.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Building, rendering, and viewing forms 15 | 16 | The corresponding scenario is [#19](https://github.com/SolidLabResearch/Challenges/issues/19). 17 | 18 | ## Problem 19 | 20 | The idea is to have a Google Forms-like interface but for the generation of RDF data. 21 | We envision an environment in which: 22 | 23 | - Form builders can generate an RDF form definition. 24 | - Form renders that can render an RDF form for end users (e.g. as HTML or as a text menu). 25 | - Form viewers that can view the generated RDF in a human friendly way. 26 | 27 | These three components can work together, for example, so that 28 | 29 | 1. a form builder creates a Doodle form, 30 | 2. a form renderer makes a HTML version to input the data, and 31 | 3. a form viewer generates a nice read-only view. 32 | 33 | See also the reports ["Drag & drop form builder to build basic RDF form definition"](./drag-drop-form-builder-to-build-basic-rdf-form-definition.md) 34 | and ["Form renderer that to view RDF form and store filled-in data in pod"](./form-renderer-to-view-form-store-data.md). 35 | 36 | ## Approved solutions 37 | 41 | 42 | We created a proof-of-concept of a form builder via challenge #64. 43 | You find the corresponding report [here](./drag-drop-form-builder-to-build-basic-rdf-form-definition.md). 44 | We created a proof-of-concept of a form renderer via challenge #65. 45 | You find the corresponding report [here](./form-renderer-to-view-form-store-data.md). 46 | 47 | There is no challenge for the form viewer, 48 | but we did create a proof-of-concept. 49 | You find a viewer for curriculum vitae [here](https://github.com/phochste/CVViewer) 50 | and a live demo [here](https://patrickhochstenbach.net/cv.html). 51 | 52 | ## Follow-up actions 53 | 54 | None. 55 | 56 | ## Future work 57 | 58 | - Create Svelte reusable components based on the code in the different repositories. 59 | -------------------------------------------------------------------------------- /reports/determining-query-equivalence-between-newly-registered-query-and-already-executing-query.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Determining query equivalence between newly registered query and already executing query 15 | 16 | The corresponding challenge is [#106](https://github.com/SolidLabResearch/Challenges/issues/106), 17 | which contributes to scenario [#16](https://github.com/SolidLabResearch/Challenges/issues/16). 18 | This challenge is an extension of challenge [#84](https://github.com/solidLabResearch/challenges/issues/84). 19 | 20 | ## Problem 21 | 25 | 26 | The [Solid Stream Aggregator](https://github.com/argahsuknesib/solid-stream-aggregator) is a service that 27 | aggregates data streams from Solid pods and stores the aggregation in another pod. 28 | This aggregation uses 29 | the [LDES in LDP](https://woutslabbinck.github.io/LDESinLDP/) specification. 30 | The user can register queries into the aggregator and 31 | generate a continuous materialized view over the streams stored in the pods. 32 | Moreover, multiple users can register the same query to the aggregator. 33 | On registering the same query, 34 | the aggregator currently instantiates a new process to compute and develop a continuous view. 35 | However, such an approach is resource-consuming and 36 | hinders the scalability of the aggregator. 37 | Therefore, there is a need for the aggregator to determine 38 | if a newly registered query is similar to an already executing query, and 39 | if so, not execute the query again but reuse the results of the already executing query. 40 | The Query Registry component of the aggregator keeps a record of 41 | the queries that are being executed currently and 42 | can be employed to identify query equivalence between 43 | a newly registered query and an already executing one. 44 | 45 | ## Approved solution 46 | 50 | 51 | We developed a [library](https://github.com/argahsuknesib/rspql-query-equivalence) to determine 52 | the equivalence between two 53 | [RSP-QL](https://re.public.polimi.it/retrieve/e0c31c0e-f3df-4599-e053-1705fe0aef77/RSP-QL-Semantics-A-Unifying%20Query%20Model%20to%20Explain%20Heterogeneity_11311-964309_Della%20Valle.pdf) 54 | queries. 55 | RSP-QL is an extension of SPARQL to support continuous querying of data streams. 56 | These queries can work with timestamp-based RDF Stream Processing (RSP) engines. 57 | We developed [this demo](https://github.com/argahsuknesib/query-equivalence-demo) to show how the library works. 58 | 59 | We made the following important technological decisions and assumptions: 60 | 61 | - Since we are only interested in demonstrating the functionality of the Query Registry of the Solid Stream Aggregator, 62 | our demo doesn't include the actual aggregation of the different data streams. 63 | In case you wish to run the aggregator with pods and 64 | are interested in the aggregation results, 65 | you can check out [this demo](https://github.com/SolidLabResearch/aggregator-description-demo). 66 | 67 | ## User flow 68 | 69 | 73 | 74 | ### Actors/actresses 75 | 76 | - User of the demo 77 | 78 | ### Preconditions 79 | 80 | - The user has Node.js installed. 81 | 82 | ### Steps 83 | 84 | 1. Clone the repository via 85 | 86 | ```shell 87 | git clone https://github.com/argahsuknesib/query-equivalence-demo.git 88 | ``` 89 | 90 | 2. Navigate to the folder `query-equivalence-demo` via 91 | 92 | ```shell 93 | cd query-equivalence-demo 94 | ``` 95 | 96 | 3. Install the dependencies via 97 | 98 | ```shell 99 | npm i 100 | ``` 101 | 102 | 4. Start the Community Solid Server instance that hosts data used by the queries via 103 | 104 | ```shell 105 | npm run start-solid-server 106 | ``` 107 | 108 | 5. Start the aggregator in a separate terminal via 109 | 110 | ```shell 111 | npm run start demo 112 | ``` 113 | 114 | 6. Register the first query 115 | 116 | ```sparql 117 | PREFIX saref: 118 | PREFIX dahccsensors: 119 | PREFIX : 120 | REGISTER RStream AS 121 | SELECT (AVG(?o) AS ?averageHR1) 122 | FROM NAMED WINDOW :w1 ON STREAM [RANGE 10 STEP 2] 123 | WHERE{ 124 | WINDOW :w1 { ?s saref:hasValue ?o . 125 | ?s saref:relatesToProperty dahccsensors:wearable.bvp .} 126 | } 127 | ``` 128 | 129 | with the aggregator in a new terminal via 130 | 131 | ```shell 132 | npm run query-one 133 | ``` 134 | 135 | The aggregator outputs the message 136 | > The query you have registered is not already executing. 137 | 7. Register the second query 138 | 139 | ```sparql 140 | PREFIX saref: 141 | PREFIX dahccsensors: 142 | PREFIX : 143 | REGISTER RStream AS 144 | SELECT (AVG(?timestamp) AS ?averageTimestamp) 145 | FROM NAMED WINDOW :w1 ON STREAM [RANGE 10 STEP 2] 146 | WHERE{ 147 | WINDOW :w1 { ?s saref:hasTimestamp ?timestamp .} 148 | } 149 | ``` 150 | 151 | with the aggregator via 152 | 153 | ```shell 154 | npm run query-two 155 | ``` 156 | 157 | The aggregator outputs the same message 158 | > The query you have registered is not already executing. 159 | 160 | Both queries are on the same data stream source, 161 | but the basic graph patterns are not isomorphic. 162 | Therefore, the aggregator registers both queries. 163 | 8. Register the third query 164 | 165 | ```sparql 166 | PREFIX saref: 167 | PREFIX dahccsensors: 168 | PREFIX : 169 | REGISTER RStream AS 170 | SELECT (AVG(?o) AS ?averageHR1) 171 | FROM NAMED WINDOW :w1 ON STREAM [RANGE 10 STEP 2] 172 | WHERE{ 173 | WINDOW :w1 { ?s saref:hasValue ?o . 174 | ?s saref:relatesToProperty dahccsensors:wearable.heartRate .} 175 | } 176 | ``` 177 | 178 | with the aggregator via 179 | 180 | ```shell 181 | npm run query-three 182 | ``` 183 | 184 | The aggregator outputs the message 185 | > The query you have registered is not already executing. 186 | 9. Register the fourth query 187 | 188 | ```sparql 189 | PREFIX saref: 190 | PREFIX dahccsensors: 191 | PREFIX : 192 | REGISTER RStream AS 193 | SELECT (AVG(?o) AS ?averageHR1) 194 | FROM NAMED WINDOW :w1 ON STREAM [RANGE 10 STEP 2] 195 | WHERE{ 196 | WINDOW :w1 { 197 | ?subject saref:relatesToProperty dahccsensors:wearable.heartRate . 198 | ?subject saref:hasValue ?object . 199 | } 200 | } 201 | ``` 202 | 203 | with the aggregator via 204 | 205 | ```shell 206 | npm run query-four 207 | ``` 208 | 209 | The aggregator outputs the message 210 | > The query you have registered is already executing. 211 | 212 | These queries are on the same data stream source and 213 | the basic graph patterns are isomorphic. 214 | Therefore, the aggregator will execute only one of the queries. 215 | 10. Register the fifth query 216 | 217 | ```sparql 218 | PREFIX saref: 219 | PREFIX dahccsensors: 220 | PREFIX : 221 | REGISTER RStream AS 222 | SELECT (AVG(?object) AS ?averageHR1) 223 | FROM NAMED WINDOW :w1 ON STREAM [RANGE 10 STEP 2] 224 | WHERE{ 225 | WINDOW :w1 { 226 | ?subject saref:relatesToProperty dahccsensors:wearable.Accelerometer . 227 | ?subject saref:hasValue ?object . 228 | } 229 | } 230 | ``` 231 | 232 | with the aggregator via 233 | 234 | ```shell 235 | npm run query-five 236 | ``` 237 | 238 | The aggregator outputs the message 239 | > The query you have registered is not already executing. 240 | 241 | 11. Register the sixth query 242 | 243 | ```sparql 244 | PREFIX saref: 245 | PREFIX dahccsensors: 246 | PREFIX : 247 | REGISTER RStream AS 248 | SELECT (AVG(?object) AS ?averageHR1) 249 | FROM NAMED WINDOW :w1 ON STREAM [RANGE 10 STEP 2] 250 | WHERE{ 251 | WINDOW :w1 { 252 | ?subject saref:relatesToProperty dahccsensors:wearable.Accelerometer . 253 | ?subject saref:hasValue ?object . 254 | } 255 | } 256 | ``` 257 | 258 | with the aggregator via 259 | 260 | ```shell 261 | npm run query-six 262 | 263 | ``` 264 | 265 | The aggregator outputs the message 266 | > The query you have registered is not already executing. 267 | 268 | For these two queries, the basic graph patterns are isomorphic, 269 | but the data stream sources are different. 270 | In this case, the aggregator will execute both queries. 271 | 272 | ### Postconditions 273 | 274 | None. 275 | 276 | ## Follow-up actions 277 | 281 | 282 | None. 283 | 284 | ## Future work 285 | 290 | 291 | - Support query containment as well as sharing of intermediate RDF result sharing 292 | between data streams. 293 | 294 | ## Lessons learned about developer experience 295 | 299 | 300 | None. 301 | -------------------------------------------------------------------------------- /reports/drag-drop-form-builder-to-build-basic-rdf-form-definition.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Drag & drop form builder to build basic RDF form definition 15 | 16 | The corresponding challenge is [#64](https://github.com/SolidLabResearch/Challenges/issues/64). 17 | 18 | ## Problem 19 | 20 | Create a drag & drop form builder that combines HTML form input fields, and 21 | generates an RDF form definition of the created form. 22 | This RDF form definition should be stored in a preferred Solid location. 23 | 24 | The basic idea is to start with a Google Forms-like interface but for the generation of RDF data. 25 | This application is one application that can be used in an environment in which: 26 | 27 | - Form builders can generate an RDF form definition. 28 | - Form renders that can render an RDF form for end users (e.g. as HTML or as a text menu). 29 | - Form viewers that can view the generated RDF in a human friendly way. 30 | 31 | These three components can work together, for example, so that 32 | 33 | 1. a form builder creates a Doodle form, 34 | 2. a form renderer makes a HTML version to input the data, and 35 | 3. a form viewer generates a nice read-only view. 36 | 37 | See also the report ["Form renderer that to view RDF form and store filled-in data in pod"](./form-renderer-to-view-form-store-data.md). 38 | 39 | ## Approved solution 40 | 41 | We developed a [Web app](https://github.com/smessie/FormGenerator) 42 | that allows users to create form definitions and share them with other users. 43 | The generated form definition is stored in a user's pod as RDF and 44 | can then be used together with a form renderer to input data. 45 | 46 | Below you find a screenshot where a form is defined with the following fields: 47 | 48 | - Title: a text field which binds to `dc:title` 49 | - Author: a text field which binds to `dc:author` 50 | - Rating: a dropdown field for which binds to ex:rating. The dropdown should contain these options: 51 | - "★ - I don't like it" binding to `ex:NotLikeIt` 52 | - "★★ - It was ok" binding to `ex:ItWasOk` 53 | - "★★★ - I liked it" binding to `ex:LikedIt` 54 | - "★★★★ - I really liked it" binding to `ex:ReallyLikedIt` 55 | - Review: a text field which binds to `dc:description` 56 | 57 | ![Screenshot of form-generator with 3 text fields and one dropdown field](./img/from-generator.png) 58 | 59 | ## User flow 60 | 61 | 65 | 66 | ### Actors/actresses 67 | 68 | - Form generator Web app 69 | - User of the Web app 70 | 71 | ### Preconditions 72 | 73 | - The user has a WebID. 74 | 75 | ### Steps 76 | 77 | 1. The user opens the Web app. 78 | 2. The user logs in with their WebID. 79 | 3. The user drags fields from the panel on the left side to the panel on the right. 80 | 4. The user fills in the details of the fields. See the example form in the "Approved solution" section. 81 | 5. The user click on the button "Save". 82 | 6. The app shows a notification confirming that the data is saved at the resource mentioned at the top. 83 | 84 | ### Postconditions 85 | 86 | - The form is stored in the user's pod at the resource mentioned at the top. 87 | 88 | ## Follow-up actions 89 | 90 | None. 91 | 92 | ## Future work 93 | 94 | None. 95 | -------------------------------------------------------------------------------- /reports/edit-pod-files-in-vs-code.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Edit pod files in Visual Studio Code 15 | 16 | The corresponding challenge is [#80](https://github.com/SolidLabResearch/Challenges/issues/80). 17 | 18 | ## Problem 19 | 20 | The goal is to create a Visual Studio Code extension similar to remote SSH that 21 | allows you to edit files on a remote pod as if they were directly on your machine. 22 | This removes the barrier of entry for developers and admins, 23 | because it allows them to 24 | 25 | - better understand what data is in the pods, and 26 | - edit the data in the pods. 27 | 28 | ## Approved solution 29 | 30 | We developed an [extension](https://marketplace.visualstudio.com/items?itemName=jeswr.solidfs) 31 | that allows users to 32 | 33 | - open directories (containers) 34 | - open files (resources) 35 | - delete files (resources) 36 | - create files (resources) 37 | - modify files (resources) 38 | 39 | You can watch a screencast [here](https://cloud.ilabt.imec.be/index.php/s/Ty2pNyqtmDn5Qsk). 40 | The source code of the extension is not publicly available. 41 | 42 | ## Follow-up actions 43 | 44 | None. 45 | 46 | ## Future work 47 | 48 | None. 49 | -------------------------------------------------------------------------------- /reports/external-service-stores-calendar-in-pod.md: -------------------------------------------------------------------------------- 1 | 14 | 15 | # External service stores calendar in pod 16 | 17 | The corresponding challenge is [#68](https://github.com/SolidLabResearch/Challenges/issues/68), 18 | which contributes to scenario [#2](https://github.com/SolidLabResearch/Challenges/issues/2). 19 | 20 | ## Problem 21 | 22 | At the moment it's possible to request a calendar from a CSS instance through the use of 23 | a [store](https://github.com/KNowledgeOnWebScale/solid-calendar-store/). 24 | But this solution is coupled to the implementation of CSS. 25 | A better solution would be to have an external service that reads the original calendar and 26 | stores it in a pod using only the methods specified by Solid. 27 | 28 | ## Approved solution 29 | 33 | 34 | Oxford HCC developed an [orchestrator](https://github.com/renyuneyun/calendar-orchestrator) that allows users to 35 | configure an automatic process that periodically retrieves their calendars, 36 | converts them to RDF, and 37 | stores them on their pods. 38 | 39 | The repository contains both a [frontend](https://github.com/renyuneyun/calendar-orchestrator/tree/main/app) and 40 | a [backend](https://github.com/renyuneyun/calendar-orchestrator/tree/main/core), but 41 | only the backend is relevant for [challenge #68](https://github.com/SolidLabResearch/Challenges/issues/68) and 42 | this report. 43 | 44 | ## User flow 45 | 46 | 50 | 51 | ### Actors/actresses 52 | 53 | - User of the orchestrator 54 | 55 | ### Preconditions 56 | 57 | - The user has a calendar that is available in the [ICS format](https://datatracker.ietf.org/doc/html/rfc5545). 58 | We assume for the steps below that the calendar is available at `http://localhost:8080/parties.ics`. 59 | It contains one event on 2023-03-17 that starts on 13:00 and ends at 19:00. 60 | - The user has a WebID. 61 | We assume for the steps below that the WebID is `https://pod.playground.solidlab.be/ash/profile/card#me`. 62 | - The user has a pod where the calendar and the configuration of the orchestrator can be stored. 63 | We assume for the steps below that the pod is located at `https://pod.playground.solidlab.be/ash/`, 64 | with `https://pod.playground.solidlab.be/` as identify provider. 65 | - The WebID has a `http://www.w3.org/ns/pim/space#storage` triple. 66 | See the [Solid WebID Profile](https://solid.github.io/webid-profile/#storage). 67 | For the WebID `https://pod.playground.solidlab.be/ash/profile/card#me` we added the triple 68 | 69 | ```turtle 70 | <#me> . 71 | ``` 72 | 73 | - The user has [HTTPie](https://httpie.io/) installed on their local machine. 74 | 75 | ### Steps 76 | 77 | 1. Clone the [orchestrator](https://github.com/renyuneyun/calendar-orchestrator) 78 | via `git clone https://github.com/renyuneyun/calendar-orchestrator.git`. 79 | 2. Navigate to the `core` folder via `cd calendar-orchestrator/core`. 80 | 3. Install the dependencies via `npm i`. 81 | 4. Run the orchestrator via `npm run build && npm run start`. 82 | 5. Open a new terminal. 83 | 6. Register the user via 84 | 85 | ```shell 86 | http POST localhost:3000/user webid=https://pod.playground.solidlab.be/ash/profile/card#me issuer=https://pod.playground.solidlab.be/ email=ash@example.com password=ash 87 | ``` 88 | 89 | 7. Get the user's information via 90 | 91 | ```shell 92 | http GET localhost:3000/user webid=https://pod.playground.solidlab.be/ash/profile/card#me 93 | ``` 94 | 95 | 8. Set user's calendar URL via 96 | 97 | ```shell 98 | http POST localhost:3000/user webid=https://pod.playground.solidlab.be/ash/profile/card#me issuer=https://pod.playground.solidlab.be/ cal_url=http://localhost:8080/parties.ics 99 | ``` 100 | 101 | 9. Update user's calendar data 102 | 103 | ```shell 104 | http POST localhost:3000/user webid=https://pod.playground.solidlab.be/ash/profile/card#me issuer=https://pod.playground.solidlab.be/ 105 | ``` 106 | 107 | ### Postconditions 108 | 109 | Find the availability calendar at `https://pod.playground.solidlab.be/ash/availability`. 110 | This is a snippet of the calendar: 111 | 112 | ```turtle 113 | @prefix schema: . 114 | 115 | 116 | schema:name "Combined of [Parties]" ; 117 | schema:event , , , , , , , . 118 | 119 | 120 | a schema:Event ; 121 | schema:name "Available for meetings" ; 122 | schema:startDate "2023-03-08T10:00:00.000Z" ; 123 | schema:endDate "2023-03-08T18:00:00.000Z" . 124 | 125 | 126 | a schema:Event ; 127 | schema:name "Available for meetings" ; 128 | schema:startDate "2023-03-09T10:00:00.000Z" ; 129 | schema:endDate "2023-03-09T18:00:00.000Z" . 130 | 131 | 132 | a schema:Event ; 133 | schema:name "Available for meetings" ; 134 | schema:startDate "2023-03-10T10:00:00.000Z" ; 135 | schema:endDate "2023-03-10T18:00:00.000Z" . 136 | 137 | 138 | a schema:Event ; 139 | schema:name "Available for meetings" ; 140 | schema:startDate "2023-03-13T10:00:00.000Z" ; 141 | schema:endDate "2023-03-13T18:00:00.000Z" . 142 | 143 | 144 | a schema:Event ; 145 | schema:name "Available for meetings" ; 146 | schema:startDate "2023-03-14T10:00:00.000Z" ; 147 | schema:endDate "2023-03-14T18:00:00.000Z" . 148 | 149 | 150 | a schema:Event ; 151 | schema:name "Available for meetings" ; 152 | schema:startDate "2023-03-15T10:00:00.000Z" ; 153 | schema:endDate "2023-03-15T18:00:00.000Z" . 154 | 155 | 156 | a schema:Event ; 157 | schema:name "Available for meetings" ; 158 | schema:startDate "2023-03-16T10:00:00.000Z" ; 159 | schema:endDate "2023-03-16T18:00:00.000Z" . 160 | 161 | 162 | a schema:Event ; 163 | schema:name "Available for meetings" ; 164 | schema:startDate "2023-03-17T10:00:00.000Z" ; 165 | schema:endDate "2023-03-17T13:00:00.000Z" . 166 | ``` 167 | 168 | On 2023-03-17 there is an event from 13:00 till 19:00 as defined by the ICS calendar at `http://localhost:8080/parties.ics`. 169 | Therefore, on that date the user is only available until 13:00. 170 | 171 | ## Follow-up actions 172 | 176 | 177 | - Check for similarities and differences with [Koreografeye](https://github.com/eyereasoner/Koreografeye). 178 | 179 | ## Future work 180 | 185 | 186 | None. 187 | -------------------------------------------------------------------------------- /reports/form-renderer-to-view-form-store-data.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Form renderer that to view RDF form and store filled-in data in pod 15 | 16 | The corresponding challenge is [#65](https://github.com/SolidLabResearch/Challenges/issues/65). 17 | 18 | ## Problem 19 | 20 | Create a form renderer that can render an RDF form definition. 21 | In this application users can in a declarative way point to 22 | 23 | - the RDF form definition, 24 | - the RDF data, and 25 | - the resource on a Solid pod where the data should be stored. 26 | 27 | This application is one application that can be used in an environment in which: 28 | 29 | - Form builders can generate an RDF form definition. 30 | - Form renders that can render an RDF form for end users (e.g. as HTML or as a text menu). 31 | - Form viewers that can view the generated RDF in a human friendly way. 32 | 33 | These three components can work together, for example, so that 34 | 35 | 1. a form builder creates a Doodle form, 36 | 2. a form renderer makes a HTML version to input the data, and 37 | 3. a form viewer generates a nice read-only view. 38 | 39 | See also the report ["Drag & drop form builder to build basic RDF form definition"](./drag-drop-form-builder-to-build-basic-rdf-form-definition.md). 40 | 41 | ## Approved solution 42 | 43 | We developed a [Web app](https://github.com/phochste/FormViewer) 44 | that allows users to 45 | 46 | - view an RDF form, and 47 | - fill in the data. 48 | 49 | You find a screenshot below for a book review form: 50 | 51 | ![Form renderer showing the fields of a form for book review](img/form-renderer.png) 52 | 53 | In the screenshot, you see the following components: 54 | 55 | - "Login" button: log in with your Solid pod. 56 | - "Show details" button: show details about the form and where the filled-in data is stored. 57 | - "New form" button: load a new form. 58 | - "Instructions" text field: nstructions related to the form. 59 | - "Title" text field: title of the book review. 60 | - "Author" text field: author of the book. 61 | - "Rate this book" dropdown field: rating you give the book. 62 | - "Review" text field: review of the book. 63 | - "Save" button: save the form. 64 | 65 | ## User flow 66 | 67 | 71 | 72 | ### Actors/actresses 73 | 74 | - Form viewer Web app 75 | - User of the Web app 76 | 77 | ### Preconditions 78 | 79 | None. 80 | 81 | ### Steps 82 | 83 | 1. The user opens the Web app at 84 | 2. The user fills in the details of the fields. See the example form in the "Approved solution" section. 85 | 3. The user click on the button "Save". 86 | 4. The app shows a notification confirming that the data is saved at the resource mentioned in the details. 87 | You see the details by clicking on the button "Show details". 88 | 89 | ### Postconditions 90 | 91 | - The filled-in data is stored at the resource mentioned in the details. 92 | 93 | ## Follow-up actions 94 | 95 | None. 96 | 97 | ## Future work 98 | 99 | None. 100 | -------------------------------------------------------------------------------- /reports/generic-query-based-data-viewer.md: -------------------------------------------------------------------------------- 1 | 15 | 16 | # Generic query-based data viewer 17 | 18 | The corresponding challenge is [#114](https://github.com/SolidLabResearch/Challenges/issues/114). 19 | 20 | ## Problem 21 | 25 | 26 | When developing apps and adding/removing/editing data in pods, 27 | it is useful to be able to easily view what data is actually in your pods. 28 | At the moment, there is no generic app that easily allows users to 29 | execute queries over multiple pods and inspect the corresponding results. 30 | 31 | ## Approved solution 32 | 36 | 37 | We developed a [Web app](https://github.com/SolidLabResearch/generic-data-viewer/releases/tag/v1.0.0) that 38 | has the following features: 39 | 40 | - Before using the app, a developer defines via a config file the SPARQL queries that should be used by the app. 41 | - Users can log in with their WebID or identity provider. 42 | - Users select the query based on their name from the sidebar. 43 | - The app shows the results of the query in a table. 44 | - Specific query variables influence how the app shows the results: 45 | - If a variable is a link to an image and the variable ends with `_img` then the app shows the actual images. 46 | - If a variable is a float and the variable ends with `_float`, the app shows the values as floats. 47 | - Users can refresh the results of a query via a button. 48 | 49 | You find a screencast [here](https://cloud.ilabt.imec.be/index.php/s/AJomCGpLjYbxmCX). 50 | You find the details on how to configure the app for your use case 51 | [here](https://github.com/SolidLabResearch/generic-data-viewer/tree/ccccc3aa882bb7c1c76fdafdf5e937ffc491d8af#configuration-file). 52 | This includes how to use your own pods and queries. 53 | 54 | 57 | We made the following important technological decisions and assumptions: 58 | 59 | - The app has the [option](https://github.com/SolidLabResearch/generic-data-viewer/tree/ccccc3aa882bb7c1c76fdafdf5e937ffc491d8af#configuration-file) 60 | to redirect requests from Comunica, which executes the queries, via a proxy. 61 | The app does this to deal with data sources that don't set the CORS headers correctly. 62 | 63 | ## User flow 64 | 65 | 69 | 70 | This user flow describes how to set up and show a demo of the app. 71 | 72 | ### Actors/actresses 73 | 74 | - User of the application. 75 | 76 | ### Preconditions 77 | 78 | - The user has Node.js installed. 79 | 80 | ### Steps 81 | 82 | 1. Clone the repository (v1.0.0) via 83 | 84 | ```shell 85 | git clone -b v1.0.0 https://github.com/SolidLabResearch/generic-data-viewer.git 86 | ``` 87 | 88 | 2. Install the dependencies via 89 | 90 | ```shell 91 | npm i 92 | ``` 93 | 94 | 3. Prepare and start the Community Solid Server with the pods via 95 | 96 | ```shell 97 | npm run prepare:pods && npm run start:pods 98 | ``` 99 | 100 | The server is ready when the following message appears: 101 | 102 | ```text 103 | Listening to server at http://localhost:3000/ 104 | ``` 105 | 106 | 4. Open another terminal. 107 | 5. Start the app via 108 | 109 | ```shell 110 | npm start 111 | ``` 112 | 113 | The app is ready when the following message appears: 114 | 115 | ```text 116 | Running CORS Anywhere on 0.0.0.0:8000 117 | ``` 118 | 119 | 6. Open another terminal. 120 | 7. Start the proxy via 121 | 122 | ```shell 123 | npm run start:proxy 124 | ``` 125 | 126 | The app is ready when the following message appears: 127 | 128 | ```text 129 | Running CORS Anywhere on 0.0.0.0:8000 130 | ``` 131 | 132 | 8. Navigate to . 133 | 9. Click on "Test query" in the sidebar. 134 | 10. The results appear in the table on the right. 135 | 11. Click on "A list of my favourite books". 136 | 12. The app shows the message "Something went wrong while preparing the query." 137 | This happens because the data source of this query requires you to be authenticated. 138 | 13. Log in with as identity provider. 139 | 14. Click on "A list of my favourite books". 140 | 15. The results appear in the table on the right. 141 | 142 | ### Postconditions 143 | 144 | None. 145 | 146 | ## Follow-up actions 147 | 151 | 152 | We will tackle these actions in this separate 153 | [repository](https://github.com/SolidLabResearch/generic-data-viewer-react-admin/) 154 | instead of the original of the Web app. 155 | 156 | - Rebuild the same functionality using [React-admin](https://marmelab.com/react-admin/). 157 | See this [issue](https://github.com/SolidLabResearch/generic-data-viewer-react-admin/issues/1). 158 | - How to deal with queries over multiple data sources where some data sources need the proxy and others do not. 159 | See this [issue](https://github.com/SolidLabResearch/generic-data-viewer-react-admin/issues/4). 160 | 161 | ## Future work 162 | 167 | 168 | We will tackle the future work in this separate 169 | [repository](https://github.com/SolidLabResearch/generic-data-viewer-react-admin/) 170 | instead of the original of the Web app. 171 | 172 | - Support Solid authentication from browser window to web worker. 173 | See this [issue](https://github.com/SolidLabResearch/generic-data-viewer-react-admin/issues/8). 174 | 175 | ## Lessons learned about developer experience 176 | 180 | 181 | None. 182 | -------------------------------------------------------------------------------- /reports/greet-user-with-their-preferred-name.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Greet user with preferred name 15 | 16 | The corresponding challenge is [#4](https://github.com/SolidLabResearch/Challenges/issues/4). 17 | 18 | ## Problem 19 | 20 | Users like to be addressed by their preferred name within apps. 21 | This is a name that they are known as, or use for themselves. 22 | In some cultures, this is the first name. 23 | It could also be a user-chosen name or nickname. 24 | Other cultures do not have the concept of a first name, so another strategy is needed. 25 | 26 | ## Approved solution 27 | 28 | We developed a [Web app](https://github.com/SolidLabResearch/SolidLoginGreeter) that 29 | shows users their preferred name based on 30 | a [set of N3 rules](https://github.com/SolidLabResearch/SolidLoginGreeter/blob/main/public/PreferencePredicates.n3). 31 | 32 | ## User flow 33 | 34 | ### Actors/actresses 35 | 36 | - Web app 37 | - User of the application 38 | 39 | ### Preconditions 40 | 41 | - The user has started the Web app via [these instructions](https://github.com/SolidLabResearch/SolidLoginGreeter#solidwelcomelogin). 42 | - The user has a WebID with at least one of [these predicates](https://github.com/SolidLabResearch/SolidLoginGreeter/blob/main/public/PreferencePredicates.n3#L9-L12). 43 | 44 | ### Steps 45 | 46 | 1. The user opens the Web app. 47 | 2. The user logs in with their WebID. 48 | 49 | ### Postconditions 50 | 51 | - The user sees their preferred name in the Web app. 52 | 53 | ## Follow-up actions 54 | 55 | - Add a function to get a person's preferred name to SolidLabLib.js ([issue](https://github.com/SolidLabResearch/SolidLabLib.js/issues/4)). 56 | 57 | ## Future work 58 | 59 | None. 60 | -------------------------------------------------------------------------------- /reports/img/acmeplugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/acmeplugin.png -------------------------------------------------------------------------------- /reports/img/form-renderer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/form-renderer.png -------------------------------------------------------------------------------- /reports/img/from-generator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/from-generator.png -------------------------------------------------------------------------------- /reports/img/google-sheet-sync-sequence-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/google-sheet-sync-sequence-diagram.png -------------------------------------------------------------------------------- /reports/img/lit-solid-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/lit-solid-login.png -------------------------------------------------------------------------------- /reports/img/location-history/approve-location-sharing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/location-history/approve-location-sharing.png -------------------------------------------------------------------------------- /reports/img/location-history/fetch-friends-location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/location-history/fetch-friends-location.png -------------------------------------------------------------------------------- /reports/img/location-history/request-friends-location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/location-history/request-friends-location.png -------------------------------------------------------------------------------- /reports/img/location-history/revoke-location-sharing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/location-history/revoke-location-sharing.png -------------------------------------------------------------------------------- /reports/img/location-history/set-up-location capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/location-history/set-up-location capture.png -------------------------------------------------------------------------------- /reports/img/perf-test-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/perf-test-server.png -------------------------------------------------------------------------------- /reports/img/solid-app-store.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/solid-app-store.png -------------------------------------------------------------------------------- /reports/img/solid-menubar-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/reports/img/solid-menubar-app.png -------------------------------------------------------------------------------- /reports/menubar-app-to-check-who-is-on-vacation.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Menubar app to check who is on vacation 15 | 16 | The corresponding challenge is [#92](https://github.com/SolidLabResearch/Challenges/issues/92). 17 | 18 | ## Problem 19 | 23 | 24 | Manually checking your calendar to quickly see who is on vacation is a hassle. 25 | It would be easier to have menubar app that shows in a glance who is on vacation today. 26 | 27 | ## Approved solution 28 | 32 | 33 | We developed a [menubar app](https://github.com/SolidLabResearch/solid-menubar-app) that 34 | shows who is when on vacation. 35 | You find a screencast of the app [here](https://cloud.ilabt.imec.be/index.php/s/HEeGsCS4PiQxaS7) 36 | and below you find a screenshot. 37 | 38 | ![img.png](img/solid-menubar-app.png) 39 | 40 | We made the following important technological decisions and assumptions: 41 | 42 | - We use the Community Solid Server-specific 43 | [Client Credentials](https://communitysolidserver.github.io/CommunitySolidServer/6.x/usage/client-credentials/) 44 | to log in and authenticate. 45 | There is an [ongoing discussion](https://github.com/solid/solid-oidc/issues/75) in 46 | the [Solid-OIDC](https://solidproject.org/TR/oidc) spec regarding 47 | the need for something like Client Credentials. 48 | - We use [Electron](https://www.electronjs.org/) because it allows us to reuse existing JavaScript libraries and 49 | make the app cross-platform. 50 | - Users have to manually provide the urls of the vacation calendars. 51 | We didn't include the automatic discovery of this information. 52 | - We assume that the vacation calendar lists the dates via the predicate `https://data.knows.idlab.ugent.be/person/office/#date`. 53 | - We assume that the name in the WebID is provided via the predicate `http://schema.org/name`. 54 | 55 | ## User flow 56 | 57 | 61 | 62 | ### Actors/actresses 63 | 64 | - Menubar app 65 | - User of the application 66 | 67 | ### Preconditions 68 | 69 | - The user has Node.js installed. 70 | 71 | ### Steps 72 | 73 | 1. Clone [the repo of the app](https://github.com/SolidLabResearch/solid-menubar-app) via 74 | 75 | ```shell 76 | git clone https://github.com/SolidLabResearch/solid-menubar-app.git 77 | ``` 78 | 79 | 2. Install the dependencies via 80 | 81 | ```shell 82 | npm i 83 | ``` 84 | 85 | 3. Navigate to the folder `pod-example-data` via 86 | 87 | ```shell 88 | cd pod-example-data 89 | ``` 90 | 91 | 4. Populate the test pods on the [SolidLab Playground](https://pod.playground.solidlab.be/) via 92 | 93 | ```shell 94 | node create-example-pods.js 95 | ``` 96 | 97 | 5. Go back to the root of the repo via 98 | 99 | ```shell 100 | cd .. 101 | ``` 102 | 103 | 6. Copy the example config file that works with the test pods via 104 | 105 | ```shell 106 | cp pod-example-data/config.json config.json 107 | ``` 108 | 109 | 7. Start the app via 110 | 111 | ```shell 112 | npm start 113 | ``` 114 | 115 | 8. The app appears in the menubar. The icon is an umbrella on a beach. 116 | 117 | ### Postconditions 118 | 119 | - When you click on the icon, 120 | it shows the vacation days. 121 | 122 | ## Follow-up actions 123 | 127 | 128 | - Clarify use of the Community Solid Server-specific 129 | [Client Credentials](https://communitysolidserver.github.io/CommunitySolidServer/6.x/usage/client-credentials/) in 130 | the README of the app ([issue](https://github.com/SolidLabResearch/solid-menubar-app/issues/2)). 131 | - The app stores the id and secret used by the Client Credentials in a JSON file on the disk of the user. 132 | Are there suggestions on how to make this safer ([issue](https://github.com/SolidLabResearch/solid-menubar-app/issues/5))? 133 | - Clarify why the app does not use [BashLib](https://github.com/SolidLabResearch/Bashlib/) ([issue](https://github.com/SolidLabResearch/solid-menubar-app/issues/3)). 134 | - Regarding the code to populate the test pods: 135 | - Investigate if this code should be in a separate library ([issue](https://github.com/SolidLabResearch/solid-menubar-app/issues/4)). 136 | - Clarify why this code did not use [BashLib](https://github.com/SolidLabResearch/Bashlib/) ([issue](https://github.com/SolidLabResearch/solid-menubar-app/issues/3)). 137 | 138 | ## Future work 139 | 144 | 145 | - There is an [ongoing discussion](https://github.com/solid/solid-oidc/issues/75) in 146 | the [Solid-OIDC](https://solidproject.org/TR/oidc) spec regarding 147 | the need for something like Client Credentials. 148 | We also have [a challenge](https://github.com/SolidLabResearch/Challenges/issues/13) about that. 149 | - How can the app use Solid-OIDC for authentication instead of Client Credentials ([issue](https://github.com/SolidLabResearch/solid-menubar-app/issues/6))? 150 | That way the app works with all Solid identity providers. 151 | -------------------------------------------------------------------------------- /reports/mermaid/agent-that-syncs-pods-and-google-sheets-diagram.txt: -------------------------------------------------------------------------------- 1 | sequenceDiagram 2 | actor agent_user as Agent user 3 | participant app as Sync agent 4 | participant resource as Resource 5 | participant sheet as Google Sheet 6 | actor sheet_user as Sheet user 7 | 8 | agent_user ->> app: 1. Configure agent via config file 9 | agent_user ->> app: 2. Start agent 10 | app ->> resource: 3. Query data 11 | resource -->> app: 4. Return data 12 | app ->> app: 5. Convert RDF data to 2D-array 13 | app ->> sheet: 6. Fill sheet with data from array 14 | 15 | sheet_user ->> sheet: 7. Edit one or more fields 16 | 17 | loop periodically 18 | app ->> sheet: 8. Query data 19 | sheet -->> app: 9. Return data 20 | app ->> app: 10. Check for changes on data 21 | alt changes detected 22 | app ->> app: 11. Convert changes to RDF data 23 | app ->> resource: 12. Write changes 24 | end 25 | end 26 | 27 | -------------------------------------------------------------------------------- /reports/orchestrator-to-forward-ldn-notifications-to-inbox-based-on-n3-rules.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Orchestrator to forward LDN notifications to LDN inbox based on N3 rules 15 | 16 | The corresponding challenge is [#49](https://github.com/SolidLabResearch/Challenges/issues/49). 17 | 18 | ## Problem 19 | 20 | A maintainer of a [Linked Data Notifications](https://www.w3.org/TR/ldn/) (LDN) inbox wants to 21 | see some automated processes happening 22 | when particular LDN notifications appear in one of her inboxes or are being sent by her. 23 | Possible automated processes include: 24 | 25 | - Auto reply to some messages 26 | - Forward the notification to the LDN inbox of another autonomous agent 27 | - Append outgoing messages to an outbox/sent container 28 | - Generate a new notification to be sent to a particular LDN inbox 29 | 30 | What should happen after receiving an incoming our outgoing message is described by an N3 rules. 31 | These rules could require read access to the pod (for example, to check the existence of a resource on the pod). 32 | An example of a rule in natural language is 33 | 34 | ```text 35 | IF inbox I contains a notification about a resource A, 36 | AND resource A exists on pod P, 37 | THEN generate new notification and send it to inbox X. 38 | ``` 39 | 40 | The automated processes and rules are executed by the orchestrator, which is an autonomous agent, on behalf of the maintainer. 41 | 42 | ## Approved solution 43 | 44 | We developed [Koreografeye](https://github.com/eyereasoner/Koreografeye) that allows users to 45 | run automated processed against Solid pods. 46 | Koreografeye provides two commands: `orch` for the orchestrator and 47 | `pol` for the policy executor. 48 | The `orch` command takes the input data, 49 | use the N3 rules to decide what to do with the data, and 50 | put the results output folder. 51 | The `pol` command takes the output of the `orch` command and 52 | executes the requested policies defined with the N3 rules. 53 | 54 | 57 | We made the following important technological decisions and assumptions: 58 | 59 | - We expect the solution to be part of a larger existing framework. 60 | Koreografeye doesn't implement some features on purpose such as 61 | scheduling, rate limits, input and outputs, priorities, and so on. 62 | For these features there are already existing tools that provide that. 63 | On other words Koreografeye should be able to be just one added component to for example an Apache Nifi installation. 64 | 65 | - The Composition of Koreografeye parts such as input, orchestration and 66 | policy execution are possible via the command line. 67 | That way it's programming language-independent. 68 | The JavaScript API is just an added feature and not the core of the design. 69 | 70 | - Developers can create a lot of plugins for policy enforcement and reasoner implementations. 71 | Component.JS was used to facilitate this. 72 | 73 | - Koreografeye makes a strict separation between reasoning and policy execution. 74 | We don't advise to create any side effects in the reasoning part for two reasons: 75 | - The rule book that the reasoner gets as input can be from external sources. 76 | We don't want arbitrary execution of code. 77 | - During the reasoning phase there is little control over possible side effects, 78 | such as when they are executed, in which order and how often. 79 | 80 | - Retrieving input from a (Solid) source is a [solved issue](https://solidproject.org/TR/protocol#reading-resources). 81 | The Koreografeye starts when an RDF resource is copied into a local storage location accessible for Koreografeye, 82 | - Retrieving the rule book from an external source is a [solved issue](https://solidproject.org/TR/protocol#reading-resources). 83 | Koreografeye expects a local storage location with zero or more rule book N3 or N3S (RDF Surfaces) files. 84 | - The order in which policy enforcements are executed is not relevant. 85 | - Rule books don't interfere with each other. 86 | Each rule book gets a new copy of the RDF input data 87 | 88 | ## User flow 89 | 90 | 94 | 95 | ### Actors/actresses 96 | 97 | - User of Koreografeye 98 | 99 | ### Preconditions 100 | 101 | - User has Node.js installed. 102 | 103 | ### Steps 104 | 105 | 1. Clone the [demo repo](https://github.com/eyereasoner/KoreografeyeDemo) via 106 | 107 | ```shell 108 | git clone https://github.com/eyereasoner/KoreografeyeDemo.git` 109 | ``` 110 | 111 | 2. Install dependencies via 112 | 113 | ```shell 114 | npm i 115 | ``` 116 | 117 | 3. Run the `orch` command to process all RDF resources in the `in` directory using the `ldn.n3` rules file via 118 | 119 | ```shell 120 | npm run orch:ldn 121 | ``` 122 | 123 | This generates the file `out/demo.ttl` as output containing the input RDF resource plus injected policies. 124 | 4. Run the `pol` command against the output of step 3 via 125 | 126 | ```shell 127 | npm run pol 128 | ``` 129 | 130 | This will send a notification to 131 | using the [SendNotificationPlugin](https://github.com/eyereasoner/Koreografeye/blob/main/src/policy/plugin/SendNotificationPlugin.ts). 132 | 133 | ### Postconditions 134 | 135 | If pointed to a real Solid pod inbox, 136 | then the notification would be available there. 137 | 138 | ## Follow-up actions 139 | 143 | 144 | - Integrate the [Event Notifications Typescript library](https://github.com/ErfgoedPod/evno) or 145 | [Bashlib](https://github.com/SolidLabResearch/Bashlib/) into Koreografeye to 146 | provide out-of-the-box importing of notifications. 147 | This is now an external dependency. 148 | - The current implementation is single threaded. 149 | Make options to specify how many threads can be used to execute the policies. 150 | 151 | ## Future work 152 | 157 | 158 | - Current systems makes no assumptions on how policies should be executed, in which order, and what to do when policies fail. 159 | Align with other groups to find a solution on how a composition of policies should be executed. 160 | 161 | ## Lessons learned about developer experience 162 | 166 | 167 | ### Solid application development is not only about Web programming 168 | 169 | For real Solid integration processes need to be automated. 170 | Resources need to be also made available, updated, deleted when no user is available and no web browser is opened. 171 | In a decentralized world 172 | we can't expect that Solid pods will keep on adding logic to provide this automation steps. 173 | External services will provide this automation capacity. 174 | 175 | ### Logic and reasoning can be external to your implementation 176 | 177 | The good part of having logic external to your application is that programmers only need to worry about 178 | their own problem domain. 179 | For example, I want that LDN notifications that are send to my pod are forwarded to my email address. 180 | This logic shouldn't be implemented by every Solid application that sends notifications to my pod. 181 | It's of no concern to these applications what kind of extra business rules are required 182 | when a notification arrives in the LDN inbox. 183 | 184 | The bad part is like everything else in a decentralized world: 185 | 186 | - Who keeps an overview of what process flows are running on your data? 187 | - Who keeps an overview of resource dependencies? 188 | 189 | For example, can I delete/update a resource when I don't know if another process still needs it? 190 | 191 | ### Possible to provide very limited remote execution near or inside pod 192 | 193 | It is possible to provide very limited remote execution near or inside a Solid pod when 194 | logic and handling side effects can be separated. 195 | An orchestrator could in principle also run inside a pod. 196 | But most probably one wants to provide it very limited capabilities to prevent users to run arbitrary code 197 | on the pod server itself. 198 | For example, an orchestrator that works only as an LDN inbox rule engine like one has in 199 | Outlook or Thunderbird would allow only moving incoming notifications to a specific container. 200 | 201 | ### Remote server-side Solid data management is in general not a solved issue 202 | 203 | Although with [Bashlib](https://github.com/SolidLabResearch/Bashlib) 204 | we have a command line tool to access a Solid pod and manage its content, 205 | remote server-side Solid data management is in general not a solved issue. 206 | Bashlib requires assumptions about specialised authentication methods for each Solid implementation. 207 | We currently depend on an authentication mechanism with 208 | [tokens](https://communitysolidserver.github.io/CommunitySolidServer/7.x/usage/client-credentials/) 209 | that only works for 210 | the [Community Solid Server](https://github.com/CommunitySolidServer/CommunitySolidServer). 211 | These tokens allow doing authenticated requests without the need for the user to log in every certain amount of time. 212 | There are other pod servers that also provide such tokens, but they have their own mechanism to do this. 213 | -------------------------------------------------------------------------------- /reports/public-css-instance-for-testing.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Public Community Solid Server instance for testing 15 | 16 | The corresponding challenge is [#75](https://github.com/SolidLabResearch/Challenges/issues/75). 17 | 18 | ## Problem 19 | 20 | It would be great to have a public [Community Solid Server](https://github.com/CommunitySolidServer/CommunitySolidServer) 21 | (CSS) instance that can be used for testing. 22 | That way developers can quickly make an account to test or demo an application. 23 | 24 | ## Approved solution 25 | 26 | We deployed a CSS instance at . 27 | Users can make accounts and 28 | have complete control over their data. 29 | The instance is reset every 24 hours, 30 | specifically at 5:00 local time in Belgium. 31 | During every reset the latest version of CSS is used. 32 | It's possible to initiate the instance with a predefined set of accounts and corresponding data. 33 | You provide the predefined accounts as follows: 34 | 35 | ```json 36 | [ 37 | { 38 | "podName": "user1", 39 | "email": "user1@pod.playground.solidlab.be", 40 | "password": "user1" 41 | }, 42 | ... 43 | { 44 | "podName": "user10", 45 | "email": "user10@pod.playground.solidlab.be", 46 | "password": "user10" 47 | } 48 | ] 49 | ``` 50 | 51 | Please contact [Pieter Heyvaert](mailto:pieter.heyvaert@ugent.be) if you would like to add predefined accounts. 52 | 53 | ## Follow-up actions 54 | 55 | None. 56 | 57 | ## Future work 58 | 59 | None. 60 | -------------------------------------------------------------------------------- /reports/read-and-write-data-in-web-app-relying-on-solid-authentication-browser-extension.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Read and write data in Web app relying on Solid authentication browser extension 15 | 16 | The corresponding challenge is [#102](https://github.com/SolidLabResearch/Challenges/issues/102). 17 | 18 | ## Problem 19 | 23 | 24 | The goal of [this browser extension](https://github.com/KNowledgeOnWebScale/solid-authentication-browser-extension/) is 25 | that requests are automatically authenticated when needed. 26 | Using this we can show that a Web app can be created that reads data from and stores data 27 | in a protected resources in a pod without the need for including Solid authentication in the Web app. 28 | 29 | ## Approved solution 30 | 34 | 35 | We developed a [Web app](https://github.com/SolidLabResearch/markdown-editor) that allows 36 | users to edit Markdown files using only GET and PUT requests. 37 | It has the following features: 38 | 39 | - Load Markdown files via GET requests. 40 | - Store Markdown files via PUT requests. 41 | - Show WebID of user if user has logged in with the Solid Authentication browser extension. 42 | - WebID and browser extension are not needed when working with public resources. 43 | - Show urls of most recent files. The urls are stored in the browser storage. 44 | 45 | You find a live version of the app [here](https://solidlabresearch.github.io/markdown-editor/) and 46 | a screencast of the app [here](https://cloud.ilabt.imec.be/index.php/s/JcqFbRzNMFztC8D). 47 | 48 | 51 | We made the following important technological decisions and assumptions: 52 | 53 | - The tool relies on the Solid authentication browser extension for requests that required authentication. 54 | No fallback is provided for when the extension is not installed. 55 | - The user knows where a new resource should be stored on the pod. 56 | They manually provide the full URL of the resource in a text-field. 57 | 58 | ## User flow 59 | 60 | 64 | 65 | ### Actors/actresses 66 | 67 | - Menubar app 68 | - User of the application 69 | 70 | ### Preconditions 71 | 72 | - The user has Node.js installed. 73 | - The user has 74 | [this version](https://github.com/KNowledgeOnWebScale/solid-authentication-browser-extension/commit/bd8d9f8466382b637a640ec2ec11caccdecafc41) 75 | of the Solid authentication browser extension installed. 76 | - The user has a WebID and pod. 77 | You can create both for testing via the [Pod Playground of SolidLab](https://pod.playground.solidlab.be/). 78 | - The user has logged in with their WebID in the browser extension. 79 | 80 | ### Steps 81 | 82 | 1. Clone [the repo of the app](https://github.com/SolidLabResearch/markdown-editor) via 83 | 84 | ```shell 85 | git clone https://github.com/SolidLabResearch/markdown-editor.git 86 | ``` 87 | 88 | 2. Install the dependencies via 89 | 90 | ```shell 91 | npm i 92 | ``` 93 | 94 | 3. Start the server via 95 | 96 | ```shell 97 | npm start 98 | ``` 99 | 100 | 4. Open Firefox and browse to . 101 | 5. In the text field at the top enter the URL for a new Markdown resource on your pod. 102 | 6. Edit the Markdown file. 103 | 7. The app automatically saves your changes. 104 | 105 | ### Postconditions 106 | 107 | - Open the resource in a new tab in your browser. 108 | You don't need the app to see its content. 109 | Note that the [Community Solid Server](https://github.com/CommunitySolidServer/CommunitySolidServer) 110 | will not show the Markdown file directly, but 111 | a rendered HTML version instead. 112 | 113 | ## Follow-up actions 114 | 115 | None. 116 | 117 | ## Future work 118 | 119 | None. 120 | -------------------------------------------------------------------------------- /reports/store-manage-share-and-query-location-history-data.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Store, manage, share and query location (history) data 15 | 16 | The corresponding challenge is [#10](https://github.com/SolidLabResearch/Challenges/issues/10). 17 | 18 | ## Problem 19 | 20 | Your location and its history are a valuable source of information for applications to offer you 21 | a more contextual user experience. 22 | 23 | You could for example do the following: 24 | 25 | - Share your current location (temporarily) with a friend without sending it to a different server. 26 | - Annotate your location history with the mode of transport you were using at that time. 27 | This allows to analyse after a certain period your mobility behavior and 28 | whether using a different mode would’ve saved you time and money 29 | (like , but then without manual data entry and with client-side query evaluation). 30 | - Use your location history to check where a certain picture in your pod was taken. 31 | - Look-up when you were at a certain location in the past. 32 | 33 | ## Approved solution 34 | 35 | We developed a [Web app](https://github.com/SolidLabResearch/LocationHistory) that 36 | allow users to capture their location from browser after logging in with their WebID. 37 | The app stores the user's raw location data as RDF which is validated against a SHACL shape. 38 | The user can also request location from other users using their WebID. 39 | These requests can be approved or revoked. 40 | 41 | You find the live version [here](https://solidlabresearch.github.io/LocationHistory/) and 42 | a screencast of a demo [here](https://cloud.ilabt.imec.be/index.php/s/YbiRfCz7LCSseNy). 43 | The screencast doesn't contain audio. 44 | 45 | Below you find sequence diagrams that explain how to 46 | 47 | 1. Set up location capture 48 | 2. Request friend's location 49 | 3. Approve location sharing 50 | 4. Fetch friend's location 51 | 5. Revoke location sharing 52 | 53 | ![Set up location capture](img/location-history/set-up-location capture.png) 54 | 55 | ![Request friend's location](img/location-history/request-friends-location.png) 56 | 57 | ![Approve location sharing](img/location-history/approve-location-sharing.png) 58 | 59 | ![Fetch friend's location](img/location-history/fetch-friends-location.png) 60 | 61 | ![Revoke location sharing](img/location-history/revoke-location-sharing.png) 62 | 63 | ## User flow 64 | 65 | ### Actors/actresses 66 | 67 | - Web app 68 | - Two users of the application, called User 1 and User 2. 69 | 70 | ### Preconditions 71 | 72 | - The user has a WebID. 73 | 74 | ### Steps 75 | 76 | 1. User 1 opens the Web app. 77 | 2. User 1 logs in with their pod. 78 | 3. User 1 clicks on the button "Post Location History". 79 | 4. The browser asks the user if the app can know the user's location. 80 | 5. User 1 clicks on the button "Allow". 81 | 6. The app shows a map. 82 | 7. The app shows the coordinates of the user's location underneath the map. 83 | 8. User 2 opens the Web app. 84 | 9. User 2 logs in with their pod. 85 | 10. User 2 clicks on the button "Post Location History". 86 | 11. The browser asks the user if the app can know the user's location. 87 | 12. User 2 clicks on the button "Allow". 88 | 13. User 2 clicks on the button "Request Friend's Location". 89 | 14. User 2 enters the WebID of User 1. 90 | 15. User 1 clicks on the button "Approve [WebID]", where `[WebID]` is the WebID of User 2. 91 | 16. User 2 sees the image of User 1 on their map. 92 | 17. User 1 clicks on the button "Revoke [WebID]", where `[WebID]` is the WebID of User 2. 93 | 18. User 2 no longer sees the image of User 1 on their map. 94 | 95 | You can see these steps also in [this screencast](https://cloud.ilabt.imec.be/index.php/s/YbiRfCz7LCSseNy). 96 | The screencast doesn't contain audio. 97 | 98 | ### Postconditions 99 | 100 | None. 101 | 102 | ## Follow-up actions 103 | 104 | None. 105 | 106 | ## Future work 107 | 108 | - [An extension that abstracts away the complexities of permissions for resource sharing between users and apps](https://github.com/SolidLabResearch/Challenges/issues/78) 109 | -------------------------------------------------------------------------------- /reports/storing-large-real-time-data-streams-in-pod-using-LDES.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Storing large real-time data streams in pod using LDES 15 | 16 | The corresponding challenge is [#82](https://github.com/SolidLabResearch/Challenges/issues/82), 17 | which contributes to scenario [#16](https://github.com/SolidLabResearch/Challenges/issues/16). 18 | 19 | ## Problem 20 | 24 | 25 | Data streams are becoming omnipresent and 26 | are a crucial component in many use cases. 27 | Storing streams in a low-cost file-based Web environment could be done using 28 | [Linked Data Event Streams](https://semiceu.github.io/LinkedDataEventStreams/) (LDES). 29 | However, pushing large volumes of high volatile data into a Solid-based LDES is not possible because 30 | the [current solution](https://github.com/woutslabbinck/SolidEventSourcing) does the partitioning of the data 31 | after all data has been retrieved, 32 | instead of in a streaming fashion. 33 | This crashes the [Community Solid Server](https://github.com/CommunitySolidServer/CommunitySolidServer) 34 | due to the high load on the server 35 | when repartitioning large amounts of data. 36 | We use data from the [DAHCC dataset](https://dahcc.idlab.ugent.be/) for this challenge, 37 | which contains data streams describing the behaviour of various patients. 38 | The streams contain over 100.000 events. 39 | 40 | We want a streaming Solid-based LDES connector that replays data and 41 | partitions this data in a streaming fashion when retrieving the data, 42 | instead of needing to wait till the whole dataset is received. 43 | Besides avoid the high load on the server, 44 | replaying allows to mimic the real-time behaviour of data streams, 45 | even though the data is historical data. 46 | This allows to showcase how solutions can process live data streams and 47 | how they can handle different data rates. 48 | 49 | ## Approved solution 50 | 54 | 55 | We developed a [tool](https://github.com/SolidLabResearch/LDES-in-SOLID-Semantic-Observations-Replay/) that 56 | replays captured streams. 57 | The tool has the following features: 58 | 59 | - The tool is pull-based as it pulls the observations from n-triples files. 60 | - The tool adds new events to the right bucket. 61 | - If new buckets are required, the tool updates the LDES. 62 | - The user can parameterize the bucket size. 63 | 64 | The repository contains both a 65 | [Web app](https://github.com/SolidLabResearch/LDES-in-SOLID-Semantic-Observations-Replay/tree/main/webapp) and 66 | a [engine](https://github.com/SolidLabResearch/LDES-in-SOLID-Semantic-Observations-Replay/tree/main/engine), but 67 | only the engine is relevant for [challenge #82](https://github.com/SolidLabResearch/Challenges/issues/82) and 68 | this report. 69 | 70 | The solution builds on [this code](https://github.com/woutslabbinck/SolidEventSourcing). 71 | The code is not included as a dependency as it was not designed as a library. 72 | We copy and pasted the parts of the code that were useful for our solution. 73 | 74 | 77 | 78 | We made the following important technological decisions and assumptions: 79 | 80 | - JavaScript/TypeScript as main development language to be in-line with current practices. 81 | - LDES to represent a stream of events detected by IOT-related devices. 82 | - Implements paginated to support loading large datasets. 83 | - Data sources are N-triples files, as they represent the state of the devices and observations 84 | as originally persisted using [Apache Feather](https://arrow.apache.org/docs/python/feather.html). 85 | - Single-user demonstration implementation, as the main goal is validating the approach, 86 | not developing a industry-ready implementation. 87 | - [N3.js](https://www.npmjs.com/package/n3) for streaming and high-throughput handling of RDF data. 88 | - Implements recursive version of the [merge sort algorithm](https://en.wikipedia.org/wiki/Merge_sort) 89 | to sort the observation based on timestamp (configurable). 90 | - Implements pointer-based algorithm to keep track of last observation/event that has been replayed. 91 | The pointer can be advanced according to either the ordering by the end-user or automatically. 92 | - Implements optimisation to manage the size of the pods. 93 | 94 | ## User flow 95 | 96 | 100 | 101 | ### Actors/actresses 102 | 103 | - User of the tool 104 | 105 | ### Preconditions 106 | 107 | Configure the engine via the following steps: 108 | 109 | 1. Clone [the repository](https://github.com/SolidLabResearch/LDES-in-SOLID-Semantic-Observations-Replay) via 110 | 111 | ```shell 112 | git clone https://github.com/SolidLabResearch/LDES-in-SOLID-Semantic-Observations-Replay 113 | ``` 114 | 115 | 2. Navigate to `LDES-in-SOLID-Semantic-Observations-Replay` via 116 | 117 | ```shell 118 | cd LDES-in-SOLID-Semantic-Observations-Replay 119 | ``` 120 | 121 | 3. Start an instance of the Community Solid Server via 122 | 123 | ```shell 124 | docker run --rm -p 3000:3000 -it solidproject/community-server:latest -c config/default.json 125 | ``` 126 | 127 | 4. Open a new terminal at the same location. 128 | 5. Navigate to `engine` via 129 | 130 | ```shell 131 | cd engine 132 | ``` 133 | 134 | 6. Install dependencies via 135 | 136 | ```shell 137 | npm i 138 | ``` 139 | 140 | 7. Download the example DAHCC dataset via 141 | 142 | ```shell 143 | curl -L https://cloud.ilabt.imec.be/index.php/s/8BatNcg2iEyJktR/download -o data/dataset_participant1_100obs 144 | ``` 145 | 146 | 8. Set the value of `datasetFolders` to the full path of the folder `engine/data` in 147 | the file `src/config/replay_properties.json`. 148 | 9. Start the engine via 149 | 150 | ```shell 151 | npm start 152 | ``` 153 | 154 | If you get an error, 155 | see the [README](https://github.com/SolidLabResearch/LDES-in-SOLID-Semantic-Observations-Replay#installation) 156 | of the repository. 157 | 158 | ### Steps 159 | 160 | 1. Get all loadable datasets using a GET request via 161 | 162 | ```shell 163 | curl http://localhost:3001/datasets 164 | ``` 165 | 166 | You get something like 167 | 168 | ```shell 169 | ["dataset_participant1_100obs","dataset_participant2_100obs"] 170 | ``` 171 | 172 | 2. Load a particular dataset using a GET request via 173 | 174 | ```shell 175 | curl http://localhost:3001/loadDataset?dataset=dataset_participant1_100obs 176 | ``` 177 | 178 | You get an empty result. 179 | 3. Check the loading progress (in quad count) using a GET request via 180 | 181 | ```shell 182 | curl http://localhost:3001/checkLoadingSize 183 | ``` 184 | 185 | You get something like 186 | 187 | ```shell 188 | [500] 189 | ``` 190 | 191 | 4. Get the actual observation count (quads / observation) using a GET request via 192 | 193 | ```shell 194 | curl http://localhost:3001/checkObservationCount 195 | ``` 196 | 197 | You get something like 198 | 199 | ```shell 200 | [100] 201 | ``` 202 | 203 | 5. Sort the loaded observations (as according to the configured TreePath) using a GET request via 204 | 205 | ```shell 206 | curl http://localhost:3001/sortObservations 207 | ``` 208 | 209 | You get something like 210 | 211 | ```shell 212 | [["https://dahcc.idlab.ugent.be/Protego/_participant1/obs0","https://dahcc.idlab.ugent.be/Protego/_participant1/obs1","https://dahcc.idlab.ugent.be/Protego/_participant1/obs2" ... ]] 213 | ``` 214 | 215 | 6. Get a sample (as in the configured chunk) set of observations using a GET request via 216 | 217 | ```shell 218 | curl http://localhost:3001/getObservations 219 | ``` 220 | 221 | You get something like 222 | 223 | ```shell 224 | [{"termType":"NamedNode","value":"https://dahcc.idlab.ugent.be/Protego/_participant1/obs0"},{"termType":"NamedNode","value":"https://dahcc.idlab.ugent.be/Protego/_participant1/obs1"} ...}] 225 | ``` 226 | 227 | 7. Replay one next observation using a GET request via 228 | 229 | ```shell 230 | curl http://localhost:3001/advanceAndPushObservationPointer 231 | ``` 232 | 233 | You get something like 234 | 235 | ```shell 236 | [1] 237 | ``` 238 | 239 | This represents the pointer to the next replayable observation. 240 | Checking the LDES in the Solid pod (default: ), 241 | you should see at least two containers (the inbox and the LDES buckets), 242 | where the LDES buckets should now contain the replayed observation, 243 | for example . 244 | 245 | 8. Replay all remaining observations using a GET request via 246 | 247 | ```shell 248 | curl http://localhost:3001/advanceAndPushObservationPointerToTheEnd 249 | ``` 250 | 251 | ### Postconditions 252 | 253 | All observations are in the pod. 254 | 255 | ## Follow-up actions 256 | 260 | 261 | None. 262 | 263 | ## Future work 264 | 269 | 270 | - Real-time replay including throttling. 271 | Challenge [#83](https://github.com/SolidLabResearch/Challenges/issues/83) is relevant, 272 | together with the [roadmap](https://github.com/SolidLabResearch/LDES-in-SOLID-Semantic-Observations-Replay#roadmap) 273 | in the solution's repository. 274 | - Elaborate filtering on the datasets used, such as selecting specific metrics that need to be replayed rather than 275 | the entire dataset. 276 | - Improve the LDES in LDP approach, if possible. 277 | -------------------------------------------------------------------------------- /reports/template.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Title 15 | 16 | 19 | 20 | 24 | 25 | The corresponding challenge is [#??](https://github.com/SolidLabResearch/Challenges/issues/??), 26 | which contributes to scenario [#??](https://github.com/SolidLabResearch/Challenges/issues/??). 27 | 28 | ## Problem 29 | 33 | 34 | ## Approved solution 35 | 39 | 40 | 43 | You find a screencast [here](??). 44 | 45 | 48 | We made the following important technological decisions and assumptions: 49 | 50 | - TODO 51 | 52 | ## User flow 53 | 54 | 58 | 59 | ### Actors/actresses 60 | 61 | ### Preconditions 62 | 63 | ### Steps 64 | 65 | ### Postconditions 66 | 67 | ## Follow-up actions 68 | 72 | 73 | ## Future work 74 | 79 | 80 | ## Lessons learned about developer experience 81 | 85 | -------------------------------------------------------------------------------- /reports/temporal-usage-control-policy-execution-for-solid-resources.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Temporal Usage Control Policy execution for Solid Resources 15 | 16 | The corresponding challenge is [#111](https://github.com/SolidLabResearch/Challenges/issues/111). 17 | 18 | ## Problem 19 | 20 | Sharing data with other people, apps, and other agents is common in the Solid ecosystem. 21 | But you might not always want to share the data forever. 22 | You might want to share specific data for a limited amount of time. 23 | Therefore, we want a proof-of-concept that shows how we can give temporary access to a resource. 24 | 25 | The [International Data Space Association (IDSA)](https://internationaldataspaces.org/) has already defined some 26 | [Usage Control Policies (UCPs)](https://international-data-spaces-association.github.io/DataspaceConnector/Documentation/v6/UsageControl) 27 | such as the Duration-restricted Data Usage Policy. 28 | It would be preferred if the implementation uses such a policy as a basis. 29 | 30 | ## Approved solution 31 | 35 | 36 | We developed two plugins for [Koreografeye](https://github.com/eyereasoner/Koreografeye): 37 | [AclPlugin](https://github.com/SolidLabResearch/Solid-Agent/blob/main/src/plugins/AclPlugin.ts) and 38 | [CronPlugin](https://github.com/SolidLabResearch/Solid-Agent/blob/main/src/plugins/CronPlugin.ts). 39 | The AclPlugin allows updating the ACL of a resource. 40 | The CronPlugin allows executing another plugin at a specific time. 41 | We also created 42 | [N3 rules](https://github.com/SolidLabResearch/Solid-Agent/blob/main/rules/usage-control/CronRule.n3) 43 | to define how and when these plugins are executed. 44 | The [Solid Agent](https://github.com/SolidLabResearch/Solid-Agent) brings all these components together: 45 | it reads the policies, uses Koreografeye to reason over the policies and the rules, and 46 | identifies what tasks need to be executed using the aforementioned plugins. 47 | You find more information about how it works 48 | [here](https://github.com/SolidLabResearch/Solid-Agent/tree/612b9efbbb7a63674d0e9350c8ac5d49427b9195/documentation/ucp#how-does-it-work). 49 | 50 | 53 | We made the following important technological decisions and assumptions: 54 | 55 | - The UCP KG is modelled as a Solid container, 56 | which furthermore requires that the Solid server supports 57 | the [Solid Notifications Protocol](https://solidproject.org/TR/notifications-protocol) v0.2.0. 58 | - This way, the agent can listen to any policy addition. 59 | - Additionally, we can then assume that the UCP KG is valid. 60 | The agent does not check whether the complete set of UCPs are valid or not. 61 | It will only execute them. 62 | Any conflicts in the UCP KG thus are the fault of the end-user, not of the agent. 63 | - For each target resource (`ids:target`), the agent MUST have `acl:Control` permission. 64 | - The [Solid Protocol](https://solidproject.org/TR/protocol) defines two options for Authorization (§11): 65 | Web Access Control (WAC) and Access Control Policy (ACP). 66 | The agent assumes that the Solid server hosting the target resources support WAC 67 | (and therefore Access Control List (ACL) resources). 68 | - The N3 rules contain built-ins that do work with the [EYE reasoner](https://github.com/eyereasoner/eye), 69 | though no guarantees can be made with other N3 reasoners. 70 | - Only the *Duration-restricted Data Usage* from 71 | [IDS Usage Control Policies](https://international-data-spaces-association.github.io/DataspaceConnector/Documentation/v6/UsageControl#ids-usage-control-policies) 72 | has been implemented and tested as N3 Rule. 73 | - Due to how [Koreografeye](https://github.com/eyereasoner/Koreografeye) extracts policies from the Reasoning Result, 74 | the cardinality of target resources and assignees can only be 1. 75 | We made a [feature request](https://github.com/eyereasoner/Koreografeye/issues/10) to solve this problem at its root. 76 | - We added the triple ` .` to the UCP to make sure we have a WebID to 77 | which we can give access (though this was not described in 78 | the [Pattern examples](https://international-data-spaces-association.github.io/DataspaceConnector/Documentation/v6/UsageControl#duration-usage-2)). 79 | - Giving Permission equals to giving read access (`acl:Read`). 80 | 81 | They are originally described [here](https://github.com/SolidLabResearch/Solid-Agent/tree/feat/cron-plugin/documentation/ucp#limitationsassumptions). 82 | 83 | ## Screencast 84 | 85 | You find a screencast of the plugin 86 | [here](https://raw.githubusercontent.com/woutslabbinck/Solid-Agent/58da48d3bf0cadf113a26911f5304456288e4441/documentation/ucp/demo-Duration-UCP.mp4). 87 | Note that the screencast has no audio, but we explain what is presented next. 88 | 89 | In this screencast, you see three windows: 90 | 91 | - On the left we have [Penny](https://penny.vincenttunru.com/) where we've logged in 92 | with WebID `https://woutslabbinck.solidcommunity.net/profile/card#me`. 93 | In this window, we can now browse resources on Solid Pods while being authenticated. 94 | - On the top right the Solid Agent in the `DemoUCPAgent.ts` configuration is running (see step 2). 95 | - On the bottom right, there is a blank terminal which we will use to send a policy to 96 | a container that we call the Usage Control Policy Knowledge Graph (UCP KG). 97 | 98 | 1. We are authenticated and 99 | see the storage of the Solid pod of [woutslabbinck](https://woutslabbinck.solidcommunity.net/profile/card#me). 100 | 2. [woutslabbinck](https://woutslabbinck.solidcommunity.net/profile/card#me) wants to access the resource at 101 | URL `http://localhost:3000/ldes`, but does not have access. 102 | 3. However, there is a policy from the owner of that resource that can be activated. 103 | This policy allows the assignee ([woutslabbinck](https://woutslabbinck.solidcommunity.net/profile/card#me)) to have 104 | read access to the [resource](http://localhost:3000/ldes) for a period of 30 seconds (`"PT30S"^^xsd:duration`). 105 | 4. In the bottom right pane we send this policy to the UCP KG, 106 | which the DemoUCPAgent then immediately enforces. 107 | 5. Now, while authenticated as [woutslabbinck](https://woutslabbinck.solidcommunity.net/profile/card#me), 108 | we can see the resource in Penny. 109 | 6. When 30 seconds have passed 110 | the DemoUCPAgent executes the final part of the policy. 111 | It takes away read access control for [woutslabbinck](https://woutslabbinck.solidcommunity.net/profile/card#me), 112 | as defined in the Usage Control Policy. 113 | 114 | ## User flow 115 | 116 | 120 | 121 | ### Actors/actresses 122 | 123 | - User of the application. 124 | 125 | ### Preconditions 126 | 127 | - The user has Node.js installed. 128 | - The user has a WebID and pod. 129 | You can create both for testing via the [Pod Playground of SolidLab](https://pod.playground.solidlab.be/). 130 | 131 | ### Steps 132 | 133 | 1. Clone [the repository](https://github.com/SolidLabResearch/Solid-Agent) via 134 | 135 | ```shell 136 | git clone https://github.com/SolidLabResearch/Solid-Agent.git 137 | ``` 138 | 139 | 2. Navigate to the folder `Solid-Agent` via 140 | 141 | ```shell 142 | cd Solid-Agent 143 | ``` 144 | 145 | 3. Check out commit 146 | [6d7c236](https://github.com/SolidLabResearch/Solid-Agent/commit/6d7c236ef7c872ae1430008708b465be6b4d027b) via 147 | 148 | ```shell 149 | git checkout 6d7c236 150 | ``` 151 | 152 | 4. Install dependencies via 153 | 154 | ```shell 155 | npm i 156 | ``` 157 | 158 | 5. Start an instance of the [Community Solid Server](https://github.com/CommunitySolidServer/CommunitySolidServer) (CSS) 159 | via 160 | 161 | ```shell 162 | npx community-solid-server -c memory-no-setup.json 163 | ``` 164 | 165 | This instance (port 3000) will contain the policies and the resource to which we will grant access. 166 | 6. Start the DemoUCPAgent via 167 | 168 | ```shell 169 | npx ts-node indexUCP.ts 170 | ``` 171 | 172 | This code also starts a CSS instance (port 3123) for the Solid Actor and 173 | creates an account so the Solid Actor has a WebID (). 174 | Furthermore, it creates a policy container () and 175 | creates a resource () which is used as target resource. 176 | 7. Open the Web app [Penny](https://penny.vincenttunru.com/). 177 | 8. Log in with your WebOID. 178 | 9. Try to read the resource . 179 | You are not able to read the resource, because you don't have access yet. 180 | 10. Add your WebID in the file `UcpSendPolicy.ts` on line 37. 181 | We will grant this WebID access in the next step. 182 | 11. Send a duration usage-restricted access UCP to the policy container via 183 | 184 | ```shell 185 | npx ts-node UcpSendPolicy.ts 186 | ``` 187 | 188 | ### Postconditions 189 | 190 | - You are able to read the resource with Penny. 191 | 192 | ## Follow-up actions 193 | 197 | 198 | - Due to how [Koreografeye](https://github.com/eyereasoner/Koreografeye) extracts policies from the Reasoning Result, 199 | the cardinality of target resources and assignees can only be 1. 200 | We made a [feature request](https://github.com/eyereasoner/Koreografeye/issues/10) to solve this problem at its root. 201 | - Investigate if the triple ` .` is the best way to add the WebID to 202 | which we give access. 203 | 204 | ## Future work 205 | 210 | 211 | - Combine temporary access with the [location app](https://github.com/SolidLabResearch/LocationHistory) 212 | of challenge [#10](https://github.com/SolidLabResearch/Challenges/issues/10). 213 | We described this in challenge [#116](https://github.com/SolidLabResearch/Challenges/issues/116) 214 | 215 | ## Lessons learned about developer experience 216 | 217 | - When manually editing WebIDs and ACL files, and introducing errors, 218 | it is hard to find these errors. 219 | It would be useful to have a dedicated library to edit these types of files. 220 | Another option would be to let the server return a 400 status code when writing invalid RDF to resources. 221 | -------------------------------------------------------------------------------- /reports/web-component-for-solid-oidc-login.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | # Web Component for Solid-OIDC login 15 | 16 | The corresponding challenge is [#125](https://github.com/SolidLabResearch/Challenges/issues/125). 17 | 18 | ## Problem 19 | 20 | When building Solid apps, allowing users to log in with their WebID or Identity Provider is crucial. 21 | Developers have to implement this functionality every time. 22 | Thus, it would improve the ease of developing Solid apps if 23 | there exists a [Web Component](https://www.webcomponents.org/introduction) that handles the logging in and out. 24 | 25 | ## Approved solution 26 | 30 | 31 | We developed a [Web Component](https://github.com/SolidLabResearch/lit-solid-login/releases/tag/v1.0.0) 32 | to log in with Solid-OIDC. 33 | We used [Lit](https://lit.dev/) to build the component. 34 | The component is framework-agnostic. 35 | You can use it with vanilla JavaScript and 36 | frameworks such as React and Vue. 37 | End-users have the option to use either their WebID or Identity Provider to log in. 38 | The minimal code that you need to use the component is 39 | 40 | ```js 41 | 44 | 45 | 46 | ``` 47 | 48 | The screenshot belows shows the result in a Web app. 49 | 50 | ![A screenshot from a Web app. 51 | It contains two radio buttons next to each other: 52 | one for "WebID" and one for "Identity Provider". 53 | Below that there is a field where the user fills in either their WebID or 54 | Identity Provider. 55 | Next to the field is the login button.](./img/lit-solid-login.png) 56 | 57 | You find a screencast [here](https://cloud.ilabt.imec.be/index.php/s/gWfBDSp5WZKaySc). 58 | You find all options to configure the component [here](https://github.com/SolidLabResearch/lit-solid-login#options). 59 | 60 | 63 | We made the following important technological decisions and assumptions: 64 | 65 | - We used Lit to build the component 66 | because Lit is part of the [Open Web Component Recommendations](https://github.com/open-wc/open-wc). 67 | - We included some minimal styling for the component. 68 | You can change the styling yourself using CSS. 69 | 70 | [PodOS](https://github.com/pod-os/PodOS) also offers a component with similar functionality, but 71 | it requires the component to be part of a `` component. 72 | `` holds the session and 73 | can give other components access to an instance of PodOS, 74 | which can do authenticated fetches using the [rdflib.js](https://github.com/linkeddata/rdflib.js/) 75 | store/fetcher that is part of it. 76 | Thus, it doesn't full the acceptance criteria of the challenge, 77 | but it does show an interesting, alternative approach. 78 | 79 | ## User flow 80 | 81 | 85 | 86 | This user flow describes how to set up a demo of the Web Component. 87 | 88 | ### Actors/actresses 89 | 90 | - User of the demo Web app. 91 | 92 | ### Preconditions 93 | 94 | - The user has Node.js installed. 95 | 96 | ### Steps 97 | 98 | 1. Clone the [repository](https://github.com/SolidLabResearch/lit-solid-login/) (v1.0.0) via 99 | 100 | ```shell 101 | git clone -b v1.0.0 https://github.com/SolidLabResearch/lit-solid-login.git 102 | ``` 103 | 104 | 2. Install the dependencies via 105 | 106 | ```shell 107 | npm i 108 | ``` 109 | 110 | 3. Start the demo via 111 | 112 | ```shell 113 | npm start 114 | ``` 115 | 116 | Keep the demo running. 117 | 4. In another terminal prepare the Solid pods via 118 | 119 | ```shell 120 | npm run prepare:pods 121 | ``` 122 | 123 | 5. Start the Solid server with the pods via 124 | 125 | ```shell 126 | npm run start:pods 127 | ``` 128 | 129 | The server is ready when the following message appears in the terminal 130 | 131 | ```text 132 | Listening to server at http://localhost:3000/ 133 | ``` 134 | 135 | Keep this process running. 136 | 137 | 6. Open a browser at . 138 | You see a Web app that uses the component. 139 | 7. Enter the WebID in the text field. 140 | 8. Click on the button "Log in". 141 | The component redirects you to the Identity Provider. 142 | 9. Fill the email `hello@example.com` and the password `abc123`. 143 | 10. Click on the button "Log in". 144 | 11. Click on the button "Authorize" 145 | The Identity Provider redirects you to the app. 146 | 12. The component shows the following message: 147 | 148 | ```text 149 | Logged in with http://localhost:3000/example/profile/card#me 150 | ``` 151 | 152 | It also shows a logout button. 153 | 13. Click on the button "Show favourite books". 154 | The resource with your favourite books is accessible when logged in. 155 | 14. The app shows the content of the resource as the JSON-LD. 156 | It uses the authenticated fetch provided by the component. 157 | 15. Click on the button "Log out". 158 | 16. The component shows it's initial state again. 159 | 160 | ### Postconditions 161 | 162 | None. 163 | 164 | ## Follow-up actions 165 | 169 | 170 | None. 171 | 172 | ## Future work 173 | 178 | 179 | None. 180 | 181 | ## Lessons learned about developer experience 182 | 186 | 187 | None. 188 | -------------------------------------------------------------------------------- /use-case-flow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidLabResearch/Challenges/6d0ed1533bde592e055086ad25a4485457b3cac5/use-case-flow.jpg -------------------------------------------------------------------------------- /use-case-flow.md: -------------------------------------------------------------------------------- 1 | # How to create challenges from a use case 2 | 3 | 1. Select your use case. 4 | For example, a use case can be an online shop based on Solid. 5 | 2. Create scenarios from your use case. 6 | A scenario describes a specific use of the system of the use case. 7 | For example, a scenario can be a user logging into our online shop and making an order 8 | by using information stored in the user's pod. 9 | 3. For every scenario do the following. 10 | 1. Create an issue in this repo with the [template](.github/ISSUE_TEMPLATE/scenario.md) called "scenario". 11 | 2. Create challenges from the scenario. 12 | For example, a challenge can be how to get the user's clothing size out of the pod and 13 | how to it use during shopping. 14 | 3. For every challenge, create an issue in this repo with the [template](.github/ISSUE_TEMPLATE/challenge.md) called "challenge". 15 | 16 | This flow is visualized in the following figure. 17 | 18 | ![The flow of how to create challenges from a use case. 19 | It contains the same steps as in the above text.](use-case-flow.jpg) 20 | -------------------------------------------------------------------------------- /use-case-flow.txt: -------------------------------------------------------------------------------- 1 | graph TD 2 | use-case[Use case] -->|Create scenarios| scenarios[Scenarios] 3 | scenarios --> select-scenario(Select scenario) 4 | select-scenario --> create-scenario(Create scenario issue on GitHub) 5 | 6 | create-scenario -->|Create challenges| challenges[Challenges] 7 | challenges --> select-challenge(Select challenge) 8 | select-challenge --> create-challenge(Create challenge issue on GitHub) 9 | create-challenge --> challenges-left{Are there challenges left?} 10 | challenges-left --> |Yes| select-challenge 11 | challenges-left --> |No| scenarios-left{Are there scenarios left?} 12 | scenarios-left --> |yes| select-scenario 13 | scenarios-left --> |No| Done 14 | --------------------------------------------------------------------------------