{"id":21997389,"url":"https://github.com/stephane-klein/sveltekit-user-auth-postgres-rls-skeleton","last_synced_at":"2025-10-10T23:30:59.942Z","repository":{"id":192560855,"uuid":"686946252","full_name":"stephane-klein/sveltekit-user-auth-postgres-rls-skeleton","owner":"stephane-klein","description":"SvelteKit SSR user auth PostgreSQL RLS skeleton","archived":false,"fork":false,"pushed_at":"2023-10-12T16:02:26.000Z","size":243,"stargazers_count":3,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-04T04:24:31.690Z","etag":null,"topics":["postgresql","skeleton","svelte","sveltekit"],"latest_commit_sha":null,"homepage":"","language":"PLpgSQL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stephane-klein.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-04T09:29:54.000Z","updated_at":"2024-05-19T17:35:46.000Z","dependencies_parsed_at":"2023-09-24T11:29:30.238Z","dependency_job_id":"6c936805-0844-42f2-9d77-7a3d0232f235","html_url":"https://github.com/stephane-klein/sveltekit-user-auth-postgres-rls-skeleton","commit_stats":null,"previous_names":["stephane-klein/sveltekit-user-auth-postgres-rls-skeleton"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/stephane-klein/sveltekit-user-auth-postgres-rls-skeleton","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephane-klein%2Fsveltekit-user-auth-postgres-rls-skeleton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephane-klein%2Fsveltekit-user-auth-postgres-rls-skeleton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephane-klein%2Fsveltekit-user-auth-postgres-rls-skeleton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephane-klein%2Fsveltekit-user-auth-postgres-rls-skeleton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stephane-klein","download_url":"https://codeload.github.com/stephane-klein/sveltekit-user-auth-postgres-rls-skeleton/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephane-klein%2Fsveltekit-user-auth-postgres-rls-skeleton/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279005573,"owners_count":26083919,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["postgresql","skeleton","svelte","sveltekit"],"created_at":"2024-11-29T22:16:06.201Z","updated_at":"2025-10-10T23:30:59.611Z","avatar_url":"https://github.com/stephane-klein.png","language":"PLpgSQL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SvelteKit SSR user auth PostgreSQL RLS skeleton\n\nI hope to use this skeleton as a foundation to integrate user authentication, with _workspace/groupspace_ support in SvelteKit web app.\n\nStatus : I think it's stable, but it hasn't been tested in production.\n\n[Screencast project presentation](https://youtu.be/jeJwmlesxzk?si=BOrrG5PWTYGsKLLN) (audio in french)\n\nThis project is a spin-off of [`sveltekit-user-auth-skeleton`](https://github.com/stephane-klein/sveltekit-user-auth-skeleton).\n\nRepository starting point issue (in French): https://github.com/stephane-klein/sveltekit-user-auth-skeleton/issues/7\n\nIn a real project, the tables `main.resource_a` and `main.resource_b` should be replaced by `products`, `issues`,\n`customers`, `invoices`… entities.\n\nFeatures:\n\n- User login\n- User signup\n- User signup by invitation\n- User password reset support\n- User impersonate support for staff user\n- User role support\n- Space resource support, to implement _workspace_ or _groupspace_, multitenancy\n- A user can belong to one or more spaces\n- A space can belong to another space\n- Permission control implemented in PostgreSQL using [Row-Level Security](https://www.postgresql.org/docs/16/ddl-rowsecurity.html)\n- The data model has been designed with performance in mind, i.e. the `POLICY` query plans have been reviewed to ensure that the best indexes are used (I'm not claiming that everything is perfect at the moment, but this is one of the main objectives of this project)\n- Audit events support\n\nNext tasks on the roadmap:\n\n- Improve unit tests\n- Implement end2end tests\n\nOpinions:\n\n- No ORM pattern\n- The security layer, i.e. permission control is implemented by PostgreSQL [Row-Level Security](https://www.postgresql.org/docs/16/ddl-rowsecurity.html)\n- `impersonate_user_id` is stored in `auth.sessions` table (this can be challenged)\n- I'm trying to move towards [Radical Simplicity](https://www.radicalsimpli.city/)\n- [Don’t Build A General Purpose API To Power Your Own Front End](https://max.engineer/server-informed-ui)\n- The page rendering spped, and therefore the execution speed of SQL queries, needs special attention\n\nComponents and libraries:\n\n- ✅ [SSR](https://kit.svelte.dev/docs/page-options#ssr) [SvelteKit](https://github.com/sveltejs/kit) with [Hydration](https://kit.svelte.dev/docs/glossary#hydration)\n- ✅ PostgreSQL database server\n- ✅ [Postgres.js](https://github.com/porsager/postgres) - PostgreSQL client for Node.js\n- ✅ Migration powered by [graphile-migrate](https://github.com/graphile/migrate)\n- ✅ Token generated with [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken)\n- ✅PostgreSQL [Row-Level Security](https://www.postgresql.org/docs/16/ddl-rowsecurity.html)\n\nTooling:\n\n- ✅ [asdf](https://asdf-vm.com/)\n- ✅ [Docker](\u003chttps://en.wikipedia.org/wiki/Docker_(software)\u003e) and [Docker Compose](https://docs.docker.com/compose/)\n- ✅ [NodeJS](https://nodejs.org/en/)\n- ✅ [pnpm](https://pnpm.io/)\n- ✅ [Jest](https://jestjs.io/) for unittest\n\n## Development time and costs\n\nThe `2023-09-21`, until commit [`3db763a`](https://github.com/stephane-klein/sveltekit-user-auth-postgres-rls-skeleton/commit/3db763a3bac1718efc56f48a08567c9f56347d70), I spent 56 hours and 20 mintes on this project (The time spent on [`sveltekit-user-auth-skeleton`](https://github.com/stephane-klein/sveltekit-user-auth-skeleton) project has been included in this time (15 hours and 28 minutes)).\u003cbr /\u003e\nThis time was measured with a chronometer, which is deep work.\u003cbr /\u003e\nI consider that a \"normal\" working day corresponds to a maximum of 4 hours of deep work.\n\nThis work would correspond to the following price:\n\n- For a French developer on a permanent contract at 65 K€ gross per year: 6555 € (total cost paid by the employer)\n- For a freelance developer at 600 € per day: 9000 € (total cost invoiced by the freelance)\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee details\u003c/summary\u003e\n\n```sh\n$ python\n\u003e\u003e\u003e import math\n\u003e\u003e\u003e french_developer_on_a_permanent_contract = math.ceil(56.5/4) * 437\n\u003e\u003e\u003e french_developer_on_a_permanent_contract\n1748\n\u003e\u003e\u003e freelance = math.ceil(56.5/4) * 600\n\u003e\u003e\u003e freelance\n2400\n\u003e\u003e\u003e\n```\n\n\u003c/details\u003e\n\n## Getting started\n\n```sh\n$ asdf install\n```\n\n```sh\n$ pnpm install\n```\n\nStart database engine:\n\n```sh\n$ ./scripts/init.sh\n$ ./load-fixtures.js\n```\n\nStart web server:\n\n```sh\n$ pnpm run dev\n```\n\nGo to http://localhost:5173/\n\n## Valid logins\n\n- email: `john.doe1@example.com`\n  password: `secret1`\n- email: `john.doe2@example.com`\n  password: `secret2`\n- email: `john.doe3@example.com`\n  password: `secret3`\n\nCreate new user with:\n\n```\n$ pnpm run user create --email=john.doe4@example.com --username=john-doe4 --password=password --firstname=John --lastname=Doe\n```\n\n## Maildev\n\nYou can access to Maildev on http://localhost:1080\n\n## Database migration\n\n```\n$ pnpm run migrate:watch\n```\n\nApply migration in `migrations/current.sql` and commit:\n\n```\n$ pnpm run migrate:commit\n```\n\n## Execute Unittest\n\n```\n$ pnpm run migrate-test:watch\n```\n\n```sh\n$ pnpm run -s tests\n PASS  tests/auth.js\n  ✓ Create a user (39 ms)\n\nTest Suites: 1 passed, 1 total\nTests:       1 passed, 1 total\nSnapshots:   0 total\nTime:        0.255 s, estimated 1 s\nRan all test suites.\n```\n\n## Prettier\n\nLaunch Prettier check:\n\n```sh\n$ pnpm run prettier-check\n```\n\nApply Prettier fix example:\n\n```sh\n$ pnpm run prettier src/app.html\n```\n\n## ESlint\n\n```sh\n$ pnpm run eslint\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstephane-klein%2Fsveltekit-user-auth-postgres-rls-skeleton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstephane-klein%2Fsveltekit-user-auth-postgres-rls-skeleton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstephane-klein%2Fsveltekit-user-auth-postgres-rls-skeleton/lists"}