diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2c236ff..ab1fe549 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,6 @@ jobs: - partman - db-utils - infra-utils - - reserved-names env: PGHOST: localhost diff --git a/MODULES.md b/MODULES.md index 4ce9f2a1..aae4464a 100644 --- a/MODULES.md +++ b/MODULES.md @@ -60,7 +60,6 @@ - [ ] `packages/utils/inflection` - String inflection utilities - [ ] `packages/utils/base32` - Base32 encoding/decoding - [ ] `packages/utils/faker` - Fake data generation -- [ ] `packages/reserved-names` - Reserved names (subdomains, usernames, slugs) nobody may claim - [ ] `packages/db-utils` - General database utilities (deep jsonb merge/set, timestamps, column smart comments) - [ ] `packages/infra-utils` - Typed parameter interface for infrastructure resource bundles (declared params, bindings, k8s quantities, admission) diff --git a/README.md b/README.md index 3774b64f..f433bdd3 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,6 @@ Each module includes its own README with detailed documentation. See individual - [`@pgpm/inflection`](https://www.npmjs.com/package/@pgpm/inflection) - String inflection utilities - [`@pgpm/base32`](https://www.npmjs.com/package/@pgpm/base32) - Base32 encoding/decoding - [`@pgpm/faker`](https://www.npmjs.com/package/@pgpm/faker) - Fake data generation for testing -- [`@pgpm/reserved-names`](https://www.npmjs.com/package/@pgpm/reserved-names) - Reserved names (subdomains, usernames, slugs) nobody may claim ### Metrics & Analytics - [`@pgpm/measurements`](https://www.npmjs.com/package/@pgpm/measurements) - Performance tracking and analytics diff --git a/packages/reserved-names/.npmignore b/packages/reserved-names/.npmignore deleted file mode 100644 index cf8a4554..00000000 --- a/packages/reserved-names/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -__tests__ -jest.config.js diff --git a/packages/reserved-names/LICENSE b/packages/reserved-names/LICENSE deleted file mode 100644 index 7b18c918..00000000 --- a/packages/reserved-names/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2025 Dan Lynch -Copyright (c) 2025 Constructive - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/reserved-names/Makefile b/packages/reserved-names/Makefile deleted file mode 100644 index d0e4bb22..00000000 --- a/packages/reserved-names/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -EXTENSION = pgpm-reserved-names -DATA = sql/pgpm-reserved-names--0.47.5.sql - -PG_CONFIG = pg_config -PGXS := $(shell $(PG_CONFIG) --pgxs) -include $(PGXS) diff --git a/packages/reserved-names/README.md b/packages/reserved-names/README.md deleted file mode 100644 index 1672c048..00000000 --- a/packages/reserved-names/README.md +++ /dev/null @@ -1,82 +0,0 @@ -# @pgpm/reserved-names - -

- -

- -

- - - - - -

- -Reserved names that nobody may claim — subdomains, usernames, slugs, or any other kind — kept as rows and checked live by one function. - -## Overview - -`@pgpm/reserved-names` keeps one shared list, as tables, and callers check it live at the moment someone claims a name. A new entry takes effect at once for every caller, with no regeneration or redeploy of the callers. - -| table | what it holds | -| --- | --- | -| `reserved_names.kinds` | categories of name: `subdomain`, `username`, `domain`, `slug` (add more with a migration) | -| `reserved_names.reasons` | why a name is reserved: `platform`, `brand`, `lookalike`, `abuse` | -| `reserved_names.names` | the entries: `kind`, `name` (lowercase), `match` (`exact` / `prefix` / `suffix`), `reason` | - -Every entry must point at a real kind and reason (foreign keys), so a typo cannot quietly create an empty category. The primary key is `(kind, name, match)`. - -The starter data, in fixtures, is the four kinds and four reasons plus a `subdomain` list: hostnames a visitor would read as the platform's own under a shared domain (`login`, `admin`, `www`, `mail`, `ns1`, …), and a `xn--` prefix entry that blocks punycode lookalikes (`аpple` with a Cyrillic `а`). The other kinds start empty. - -## Installation - -```bash -pgpm install @pgpm/reserved-names -pgpm deploy -``` - -## Usage - -```sql -SELECT reserved_names.is_reserved('subdomain', 'login'); -- true -SELECT reserved_names.is_reserved('subdomain', 'LOGIN'); -- true (case-insensitive) -SELECT reserved_names.is_reserved('subdomain', 'xn--pple-43d'); -- true (prefix entry) -SELECT reserved_names.is_reserved('subdomain', 'mystore'); -- false -SELECT reserved_names.is_reserved('username', 'login'); -- false (kinds are separate) - -SELECT name, match, reason FROM reserved_names.reserved_by('subdomain', 'xn--pple-43d'); --- xn-- | prefix | lookalike -``` - -- `is_reserved(kind, name) RETURNS boolean`: true when any entry matches. -- `reserved_by(kind, name) RETURNS SETOF reserved_names.names`: the matching entries, so an error can say why. - -Both are `STABLE` SQL, lowercase `kind` and `name` before comparing, and treat `NULL` as not reserved. Matching: - -- `exact`: the name itself. -- `prefix`: every name starting with it (`xn--`, `staff-`). -- `suffix`: every name ending with it. `.example.com` blocks `shop.example.com`, but not `example.com` itself (add an `exact` entry for that) and not `notexample.com`. - -### Adding names - -The list changes only through migrations. Add a pgpm fixture change that inserts rows: - -```sql -INSERT INTO reserved_names.names (kind, name, match, reason) VALUES - ('subdomain', 'www2', 'exact', 'platform'), - ('subdomain', 'staff-', 'prefix', 'platform'), - ('domain', '.example.com', 'suffix', 'brand'), - ('username', 'support', 'exact', 'platform'); -``` - -A new category or reason is a row in `kinds` or `reasons` first. - -## Access - -Everyone can read the three tables and call both functions, so a UI can say "that name is reserved" before submitting. The list is public, so there is no row-level security. No role is granted `INSERT`, `UPDATE` or `DELETE`: only the owner (migrations, or a `SECURITY DEFINER` function it owns) can change it. - -## Testing - -```bash -pnpm test -``` diff --git a/packages/reserved-names/__tests__/reserved-names.test.ts b/packages/reserved-names/__tests__/reserved-names.test.ts deleted file mode 100644 index 7f2f8a76..00000000 --- a/packages/reserved-names/__tests__/reserved-names.test.ts +++ /dev/null @@ -1,222 +0,0 @@ -import { getConnections, PgTestClient } from 'pgsql-test'; - -let pg: PgTestClient; -let db: PgTestClient; -let teardown: () => Promise; - -beforeAll(async () => { - ({ pg, db, teardown } = await getConnections()); -}); - -afterAll(async () => { - await teardown(); -}); - -beforeEach(async () => { - await pg.beforeEach(); - await db.beforeEach(); -}); - -afterEach(async () => { - await db.afterEach(); - await pg.afterEach(); -}); - -const isReserved = async (client: PgTestClient, kind: string, name: string) => { - const { is_reserved } = await client.one( - `SELECT reserved_names.is_reserved($1, $2) AS is_reserved`, - [kind, name] - ); - return is_reserved; -}; - -describe('reserved_names.is_reserved', () => { - it.each(['login', 'admin', 'www', 'status', 'LOGIN', 'Admin'])( - 'reserves the exact subdomain %s, in any case', - async (name) => { - expect(await isReserved(pg, 'subdomain', name)).toBe(true); - } - ); - - it.each(['mystore', 'login2', 'my-login', 'api-docs', 'administrators'])( - 'leaves %s free', - async (name) => { - expect(await isReserved(pg, 'subdomain', name)).toBe(false); - } - ); - - it('reserves every punycode label through the xn-- prefix entry', async () => { - expect(await isReserved(pg, 'subdomain', 'xn--pple-43d')).toBe(true); - expect(await isReserved(pg, 'subdomain', 'XN--80ak6aa92e')).toBe(true); - }); - - it('matches the kind in any case', async () => { - expect(await isReserved(pg, 'Subdomain', 'login')).toBe(true); - }); - - it('keeps kinds apart', async () => { - expect(await isReserved(pg, 'username', 'login')).toBe(false); - - await pg.query( - `INSERT INTO reserved_names.names (kind, name, reason) VALUES ('username', 'support', 'platform')` - ); - expect(await isReserved(pg, 'username', 'Support')).toBe(true); - expect(await isReserved(pg, 'subdomain', 'support')).toBe(true); - expect(await isReserved(pg, 'slug', 'support')).toBe(false); - }); - - it('reserves every name ending in a suffix entry', async () => { - await pg.query(` - INSERT INTO reserved_names.names (kind, name, match, reason) VALUES - ('domain', 'constructive.io', 'exact', 'brand'), - ('domain', '.constructive.io', 'suffix', 'brand') - `); - expect(await isReserved(pg, 'domain', 'constructive.io')).toBe(true); - expect(await isReserved(pg, 'domain', 'shop.Constructive.io')).toBe(true); - expect(await isReserved(pg, 'domain', 'notconstructive.io')).toBe(false); - expect(await isReserved(pg, 'domain', 'constructive.io.evil.com')).toBe(false); - }); - - it('picks up a newly added name and prefix at once', async () => { - expect(await isReserved(pg, 'subdomain', 'www2')).toBe(false); - expect(await isReserved(pg, 'subdomain', 'staff-east')).toBe(false); - - await pg.query(` - INSERT INTO reserved_names.names (kind, name, match, reason) VALUES - ('subdomain', 'www2', 'exact', 'platform'), - ('subdomain', 'staff-', 'prefix', 'platform') - `); - - expect(await isReserved(pg, 'subdomain', 'www2')).toBe(true); - expect(await isReserved(pg, 'subdomain', 'staff-east')).toBe(true); - expect(await isReserved(pg, 'subdomain', 'staff')).toBe(false); - }); - - it('treats a NULL name or kind as not reserved', async () => { - expect(await isReserved(pg, 'subdomain', null as unknown as string)).toBe(false); - expect(await isReserved(pg, null as unknown as string, 'login')).toBe(false); - }); -}); - -describe('reserved_names.reserved_by', () => { - it('says which entries reserve a name and why', async () => { - const rows = await pg.any( - `SELECT name, match, reason FROM reserved_names.reserved_by('subdomain', 'xn--pple-43d')` - ); - expect(rows).toEqual([{ name: 'xn--', match: 'prefix', reason: 'lookalike' }]); - }); - - it('returns nothing for a free name', async () => { - const rows = await pg.any(`SELECT * FROM reserved_names.reserved_by('subdomain', 'mystore')`); - expect(rows).toEqual([]); - }); -}); - -describe('the starter data', () => { - it('has the four kinds and four reasons', async () => { - const kinds = await pg.any(`SELECT kind FROM reserved_names.kinds ORDER BY kind`); - expect(kinds.map((r) => r.kind)).toEqual(['domain', 'slug', 'subdomain', 'username']); - const reasons = await pg.any(`SELECT reason FROM reserved_names.reasons ORDER BY reason`); - expect(reasons.map((r) => r.reason)).toEqual(['abuse', 'brand', 'lookalike', 'platform']); - }); - - it('reserves no api- prefix', async () => { - expect(await isReserved(pg, 'subdomain', 'api-docs')).toBe(false); - expect(await isReserved(pg, 'subdomain', 'api')).toBe(true); - }); -}); - -describe('reserved_names.names', () => { - it('rejects names that are not lowercase', async () => { - await expect( - pg.query(`INSERT INTO reserved_names.names (kind, name, reason) VALUES ('subdomain', 'Shop', 'platform')`) - ).rejects.toThrow(/names_name_check/); - }); - - it('rejects an empty name', async () => { - await expect( - pg.query(`INSERT INTO reserved_names.names (kind, name, reason) VALUES ('subdomain', '', 'platform')`) - ).rejects.toThrow(/names_name_check/); - }); - - it('rejects an unknown kind', async () => { - await expect( - pg.query(`INSERT INTO reserved_names.names (kind, name, reason) VALUES ('usrname', 'shop', 'platform')`) - ).rejects.toThrow(/names_kind_fkey/); - }); - - it('rejects an unknown reason', async () => { - await expect( - pg.query(`INSERT INTO reserved_names.names (kind, name, reason) VALUES ('subdomain', 'shop', 'because')`) - ).rejects.toThrow(/names_reason_fkey/); - }); - - it('requires a reason', async () => { - await expect( - pg.query(`INSERT INTO reserved_names.names (kind, name) VALUES ('subdomain', 'shop')`) - ).rejects.toThrow(/null value in column "reason"/); - }); - - it('rejects an unknown match type', async () => { - await expect( - pg.query(`INSERT INTO reserved_names.names (kind, name, match, reason) VALUES ('subdomain', 'shop', 'regex', 'platform')`) - ).rejects.toThrow(/names_match_check/); - }); - - it('rejects a duplicate entry', async () => { - await expect( - pg.query(`INSERT INTO reserved_names.names (kind, name, reason) VALUES ('subdomain', 'login', 'platform')`) - ).rejects.toThrow(/names_pkey/); - }); - - it('allows the same name as exact and as a prefix', async () => { - await pg.query( - `INSERT INTO reserved_names.names (kind, name, match, reason) VALUES ('subdomain', 'login', 'prefix', 'platform')` - ); - expect(await isReserved(pg, 'subdomain', 'login-now')).toBe(true); - }); -}); - -describe('reserved_names.kinds', () => { - it('rejects a malformed kind', async () => { - await expect( - pg.query(`INSERT INTO reserved_names.kinds (kind, description) VALUES ('Sub Domain', 'x')`) - ).rejects.toThrow(/kinds_kind_check/); - }); - - it('takes a new kind for later use', async () => { - await pg.query(`INSERT INTO reserved_names.kinds (kind, description) VALUES ('team_slug', 'A team handle')`); - await pg.query( - `INSERT INTO reserved_names.names (kind, name, reason) VALUES ('team_slug', 'staff', 'platform')` - ); - expect(await isReserved(pg, 'team_slug', 'staff')).toBe(true); - }); -}); - -describe.each(['anonymous', 'authenticated'])('as %s', (role) => { - beforeEach(() => { - db.setContext({ role }); - }); - - it('can check a name and read the lists', async () => { - expect(await isReserved(db, 'subdomain', 'login')).toBe(true); - for (const table of ['names', 'kinds', 'reasons']) { - const { count } = await db.one(`SELECT count(*)::int AS count FROM reserved_names.${table}`); - expect(count).toBeGreaterThan(0); - } - const rows = await db.any(`SELECT reason FROM reserved_names.reserved_by('subdomain', 'login')`); - expect(rows).toEqual([{ reason: 'platform' }]); - }); - - it.each([ - ['names', `INSERT INTO reserved_names.names (kind, name, reason) VALUES ('subdomain', 'mine', 'platform')`], - ['names', `UPDATE reserved_names.names SET reason = 'brand' WHERE name = 'login'`], - ['names', `DELETE FROM reserved_names.names WHERE name = 'login'`], - ['kinds', `INSERT INTO reserved_names.kinds (kind, description) VALUES ('mine', 'x')`], - ['kinds', `DELETE FROM reserved_names.kinds WHERE kind = 'slug'`], - ['reasons', `INSERT INTO reserved_names.reasons (reason, description) VALUES ('mine', 'x')`], - ['reasons', `DELETE FROM reserved_names.reasons WHERE reason = 'abuse'`] - ])('cannot change %s: %s', async (table, sql) => { - await expect(db.query(sql)).rejects.toThrow(new RegExp(`permission denied for table ${table}`)); - }); -}); diff --git a/packages/reserved-names/deploy/schemas/reserved_names/procedures/is_reserved.sql b/packages/reserved-names/deploy/schemas/reserved_names/procedures/is_reserved.sql deleted file mode 100644 index e06cfe41..00000000 --- a/packages/reserved-names/deploy/schemas/reserved_names/procedures/is_reserved.sql +++ /dev/null @@ -1,16 +0,0 @@ --- Deploy schemas/reserved_names/procedures/is_reserved to pg - --- requires: schemas/reserved_names/schema --- requires: schemas/reserved_names/procedures/reserved_by - -BEGIN; - -CREATE FUNCTION reserved_names.is_reserved(kind text, name text) RETURNS boolean AS $$ - SELECT EXISTS (SELECT 1 FROM reserved_names.reserved_by(is_reserved.kind, is_reserved.name)); -$$ LANGUAGE sql STABLE; - -COMMENT ON FUNCTION reserved_names.is_reserved(text, text) IS 'True when name (any case) is reserved for kind'; - -GRANT EXECUTE ON FUNCTION reserved_names.is_reserved(text, text) TO public; - -COMMIT; diff --git a/packages/reserved-names/deploy/schemas/reserved_names/procedures/reserved_by.sql b/packages/reserved-names/deploy/schemas/reserved_names/procedures/reserved_by.sql deleted file mode 100644 index a8b0b87b..00000000 --- a/packages/reserved-names/deploy/schemas/reserved_names/procedures/reserved_by.sql +++ /dev/null @@ -1,23 +0,0 @@ --- Deploy schemas/reserved_names/procedures/reserved_by to pg - --- requires: schemas/reserved_names/schema --- requires: schemas/reserved_names/tables/names/table - -BEGIN; - -CREATE FUNCTION reserved_names.reserved_by(kind text, name text) RETURNS SETOF reserved_names.names AS $$ - SELECT n.* - FROM reserved_names.names n - WHERE n.kind = pg_catalog.lower(reserved_by.kind) - AND CASE n.match - WHEN 'exact' THEN n.name = pg_catalog.lower(reserved_by.name) - WHEN 'prefix' THEN pg_catalog.starts_with(pg_catalog.lower(reserved_by.name), n.name) - WHEN 'suffix' THEN pg_catalog.right(pg_catalog.lower(reserved_by.name), pg_catalog.length(n.name)) = n.name - END; -$$ LANGUAGE sql STABLE; - -COMMENT ON FUNCTION reserved_names.reserved_by(text, text) IS 'The entries (with their reason) that reserve name for kind; empty when it is free'; - -GRANT EXECUTE ON FUNCTION reserved_names.reserved_by(text, text) TO public; - -COMMIT; diff --git a/packages/reserved-names/deploy/schemas/reserved_names/schema.sql b/packages/reserved-names/deploy/schemas/reserved_names/schema.sql deleted file mode 100644 index 18e91bf5..00000000 --- a/packages/reserved-names/deploy/schemas/reserved_names/schema.sql +++ /dev/null @@ -1,9 +0,0 @@ --- Deploy schemas/reserved_names/schema to pg - -BEGIN; - -CREATE SCHEMA reserved_names; - -GRANT USAGE ON SCHEMA reserved_names TO public; - -COMMIT; diff --git a/packages/reserved-names/deploy/schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture.sql b/packages/reserved-names/deploy/schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture.sql deleted file mode 100644 index 23a82ae2..00000000 --- a/packages/reserved-names/deploy/schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture.sql +++ /dev/null @@ -1,14 +0,0 @@ --- Deploy schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture to pg - --- requires: schemas/reserved_names/schema --- requires: schemas/reserved_names/tables/kinds/table - -BEGIN; - -INSERT INTO reserved_names.kinds (kind, description) VALUES - ('subdomain', 'A label under a shared domain, like login in login.example.com'), - ('username', 'A person''s handle'), - ('domain', 'A whole domain name, like example.com'), - ('slug', 'A name in a URL path, like an organization or app slug'); - -COMMIT; diff --git a/packages/reserved-names/deploy/schemas/reserved_names/tables/kinds/table.sql b/packages/reserved-names/deploy/schemas/reserved_names/tables/kinds/table.sql deleted file mode 100644 index f1bc498b..00000000 --- a/packages/reserved-names/deploy/schemas/reserved_names/tables/kinds/table.sql +++ /dev/null @@ -1,16 +0,0 @@ --- Deploy schemas/reserved_names/tables/kinds/table to pg - --- requires: schemas/reserved_names/schema - -BEGIN; - -CREATE TABLE reserved_names.kinds ( - kind text PRIMARY KEY CHECK (kind ~ '^[a-z][a-z0-9_]*$'), - description text NOT NULL -); - -COMMENT ON TABLE reserved_names.kinds IS 'Categories of names that can be reserved: subdomain, username, domain, slug, ...'; - -GRANT SELECT ON TABLE reserved_names.kinds TO public; - -COMMIT; diff --git a/packages/reserved-names/deploy/schemas/reserved_names/tables/names/fixtures/1792800000002_fixture.sql b/packages/reserved-names/deploy/schemas/reserved_names/tables/names/fixtures/1792800000002_fixture.sql deleted file mode 100644 index a6ca21c2..00000000 --- a/packages/reserved-names/deploy/schemas/reserved_names/tables/names/fixtures/1792800000002_fixture.sql +++ /dev/null @@ -1,72 +0,0 @@ --- Deploy schemas/reserved_names/tables/names/fixtures/1792800000002_fixture to pg - --- requires: schemas/reserved_names/schema --- requires: schemas/reserved_names/tables/names/table --- requires: schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture --- requires: schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture - -BEGIN; - -INSERT INTO reserved_names.names (kind, name, match, reason) VALUES - ('subdomain', 'www', 'exact', 'platform'), - ('subdomain', 'api', 'exact', 'platform'), - ('subdomain', 'auth', 'exact', 'platform'), - ('subdomain', 'login', 'exact', 'platform'), - ('subdomain', 'logout', 'exact', 'platform'), - ('subdomain', 'signin', 'exact', 'platform'), - ('subdomain', 'signup', 'exact', 'platform'), - ('subdomain', 'register', 'exact', 'platform'), - ('subdomain', 'admin', 'exact', 'platform'), - ('subdomain', 'administrator', 'exact', 'platform'), - ('subdomain', 'root', 'exact', 'platform'), - ('subdomain', 'app', 'exact', 'platform'), - ('subdomain', 'apps', 'exact', 'platform'), - ('subdomain', 'dashboard', 'exact', 'platform'), - ('subdomain', 'console', 'exact', 'platform'), - ('subdomain', 'account', 'exact', 'platform'), - ('subdomain', 'accounts', 'exact', 'platform'), - ('subdomain', 'billing', 'exact', 'platform'), - ('subdomain', 'pay', 'exact', 'platform'), - ('subdomain', 'payments', 'exact', 'platform'), - ('subdomain', 'checkout', 'exact', 'platform'), - ('subdomain', 'support', 'exact', 'platform'), - ('subdomain', 'help', 'exact', 'platform'), - ('subdomain', 'status', 'exact', 'platform'), - ('subdomain', 'docs', 'exact', 'platform'), - ('subdomain', 'mail', 'exact', 'platform'), - ('subdomain', 'email', 'exact', 'platform'), - ('subdomain', 'smtp', 'exact', 'platform'), - ('subdomain', 'imap', 'exact', 'platform'), - ('subdomain', 'ftp', 'exact', 'platform'), - ('subdomain', 'ns', 'exact', 'platform'), - ('subdomain', 'ns1', 'exact', 'platform'), - ('subdomain', 'ns2', 'exact', 'platform'), - ('subdomain', 'mx', 'exact', 'platform'), - ('subdomain', 'cdn', 'exact', 'platform'), - ('subdomain', 'static', 'exact', 'platform'), - ('subdomain', 'assets', 'exact', 'platform'), - ('subdomain', 'files', 'exact', 'platform'), - ('subdomain', 'storage', 'exact', 'platform'), - ('subdomain', 'media', 'exact', 'platform'), - ('subdomain', 'ws', 'exact', 'platform'), - ('subdomain', 'wss', 'exact', 'platform'), - ('subdomain', 'graphql', 'exact', 'platform'), - ('subdomain', 'modules', 'exact', 'platform'), - ('subdomain', 'agent', 'exact', 'platform'), - ('subdomain', 'compute', 'exact', 'platform'), - ('subdomain', 'machines', 'exact', 'platform'), - ('subdomain', 'cluster', 'exact', 'platform'), - ('subdomain', 'migrate', 'exact', 'platform'), - ('subdomain', 'internal', 'exact', 'platform'), - ('subdomain', 'system', 'exact', 'platform'), - ('subdomain', 'platform', 'exact', 'platform'), - ('subdomain', 'security', 'exact', 'platform'), - ('subdomain', 'sso', 'exact', 'platform'), - ('subdomain', 'oauth', 'exact', 'platform'), - ('subdomain', 'id', 'exact', 'platform'), - ('subdomain', 'identity', 'exact', 'platform'), - ('subdomain', 'verify', 'exact', 'platform'), - ('subdomain', 'secure', 'exact', 'platform'), - ('subdomain', 'xn--', 'prefix', 'lookalike'); - -COMMIT; diff --git a/packages/reserved-names/deploy/schemas/reserved_names/tables/names/indexes/names_reason_idx.sql b/packages/reserved-names/deploy/schemas/reserved_names/tables/names/indexes/names_reason_idx.sql deleted file mode 100644 index 21df6795..00000000 --- a/packages/reserved-names/deploy/schemas/reserved_names/tables/names/indexes/names_reason_idx.sql +++ /dev/null @@ -1,10 +0,0 @@ --- Deploy schemas/reserved_names/tables/names/indexes/names_reason_idx to pg - --- requires: schemas/reserved_names/schema --- requires: schemas/reserved_names/tables/names/table - -BEGIN; - -CREATE INDEX names_reason_idx ON reserved_names.names (reason); - -COMMIT; diff --git a/packages/reserved-names/deploy/schemas/reserved_names/tables/names/table.sql b/packages/reserved-names/deploy/schemas/reserved_names/tables/names/table.sql deleted file mode 100644 index 36ea0720..00000000 --- a/packages/reserved-names/deploy/schemas/reserved_names/tables/names/table.sql +++ /dev/null @@ -1,23 +0,0 @@ --- Deploy schemas/reserved_names/tables/names/table to pg - --- requires: schemas/reserved_names/schema --- requires: schemas/reserved_names/tables/kinds/table --- requires: schemas/reserved_names/tables/reasons/table - -BEGIN; - -CREATE TABLE reserved_names.names ( - kind text NOT NULL REFERENCES reserved_names.kinds (kind), - name text NOT NULL CHECK (name <> '' AND name = lower(name)), - match text NOT NULL DEFAULT 'exact' CHECK (match IN ('exact', 'prefix', 'suffix')), - reason text NOT NULL REFERENCES reserved_names.reasons (reason), - PRIMARY KEY (kind, name, match) -); - -COMMENT ON TABLE reserved_names.names IS 'Names nobody may claim, by kind. Changed only by migrations.'; -COMMENT ON COLUMN reserved_names.names.name IS 'The reserved name, lowercase'; -COMMENT ON COLUMN reserved_names.names.match IS 'exact: the name itself; prefix: every name starting with it; suffix: every name ending with it'; - -GRANT SELECT ON TABLE reserved_names.names TO public; - -COMMIT; diff --git a/packages/reserved-names/deploy/schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture.sql b/packages/reserved-names/deploy/schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture.sql deleted file mode 100644 index 31b1d9ef..00000000 --- a/packages/reserved-names/deploy/schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture.sql +++ /dev/null @@ -1,14 +0,0 @@ --- Deploy schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture to pg - --- requires: schemas/reserved_names/schema --- requires: schemas/reserved_names/tables/reasons/table - -BEGIN; - -INSERT INTO reserved_names.reasons (reason, description) VALUES - ('platform', 'Reads as the platform''s own (login, admin, status, ...)'), - ('brand', 'Our brand or product names'), - ('lookalike', 'Can be made to look like another name, e.g. punycode'), - ('abuse', 'Offensive or used for abuse'); - -COMMIT; diff --git a/packages/reserved-names/deploy/schemas/reserved_names/tables/reasons/table.sql b/packages/reserved-names/deploy/schemas/reserved_names/tables/reasons/table.sql deleted file mode 100644 index 5f0b48f2..00000000 --- a/packages/reserved-names/deploy/schemas/reserved_names/tables/reasons/table.sql +++ /dev/null @@ -1,16 +0,0 @@ --- Deploy schemas/reserved_names/tables/reasons/table to pg - --- requires: schemas/reserved_names/schema - -BEGIN; - -CREATE TABLE reserved_names.reasons ( - reason text PRIMARY KEY CHECK (reason ~ '^[a-z][a-z0-9_]*$'), - description text NOT NULL -); - -COMMENT ON TABLE reserved_names.reasons IS 'Why a name is reserved: platform, brand, lookalike, abuse, ...'; - -GRANT SELECT ON TABLE reserved_names.reasons TO public; - -COMMIT; diff --git a/packages/reserved-names/jest.config.js b/packages/reserved-names/jest.config.js deleted file mode 100644 index 4108cf46..00000000 --- a/packages/reserved-names/jest.config.js +++ /dev/null @@ -1,16 +0,0 @@ -/** @type {import('ts-jest').JestConfigWithTsJest} */ -module.exports = { - forceExit: true, - preset: 'ts-jest', - testEnvironment: 'node', - - // Match both __tests__ and colocated test files - testMatch: ['**/?(*.)+(test|spec).{ts,tsx,js,jsx}'], - - // Ignore build artifacts and type declarations - testPathIgnorePatterns: ['/dist/', '\\.d\\.ts$'], - modulePathIgnorePatterns: ['/dist/'], - watchPathIgnorePatterns: ['/dist/'], - - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], -}; diff --git a/packages/reserved-names/package.json b/packages/reserved-names/package.json deleted file mode 100644 index 76517cfc..00000000 --- a/packages/reserved-names/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "@pgpm/reserved-names", - "version": "0.47.5", - "description": "Reserved names (subdomains, usernames, domains, slugs, ...) that nobody may claim, as tables checked live by reserved_names.is_reserved(kind, name)", - "author": "Dan Lynch ", - "contributors": [ - "Constructive " - ], - "keywords": [ - "postgresql", - "pgpm", - "reserved", - "names", - "subdomains" - ], - "publishConfig": { - "access": "public" - }, - "scripts": { - "bundle": "pgpm package", - "test": "jest", - "test:watch": "jest --watch" - }, - "dependencies": { - "@pgpm/verify": "workspace:*" - }, - "devDependencies": { - "pgpm": "^5" - }, - "repository": { - "type": "git", - "url": "https://github.com/constructive-io/pgpm-modules" - }, - "homepage": "https://github.com/constructive-io/pgpm-modules", - "bugs": { - "url": "https://github.com/constructive-io/pgpm-modules/issues" - } -} diff --git a/packages/reserved-names/pgpm-reserved-names.control b/packages/reserved-names/pgpm-reserved-names.control deleted file mode 100644 index c19d9863..00000000 --- a/packages/reserved-names/pgpm-reserved-names.control +++ /dev/null @@ -1,7 +0,0 @@ -# pgpm-reserved-names extension -comment = 'pgpm-reserved-names extension' -default_version = '0.47.5' -module_pathname = '$libdir/pgpm-reserved-names' -requires = 'plpgsql,pgpm-verify' -relocatable = false -superuser = false diff --git a/packages/reserved-names/pgpm.plan b/packages/reserved-names/pgpm.plan deleted file mode 100644 index 1ad28cca..00000000 --- a/packages/reserved-names/pgpm.plan +++ /dev/null @@ -1,14 +0,0 @@ -%syntax-version=1.0.0 -%project=pgpm-reserved-names -%uri=pgpm-reserved-names - -schemas/reserved_names/schema [pgpm-verify:procedures/assert_function] 2026-10-22T19:40:00Z devin # add schemas/reserved_names/schema -schemas/reserved_names/tables/kinds/table [schemas/reserved_names/schema] 2026-10-22T19:40:00Z devin # add schemas/reserved_names/tables/kinds/table -schemas/reserved_names/tables/reasons/table [schemas/reserved_names/schema] 2026-10-22T19:40:00Z devin # add schemas/reserved_names/tables/reasons/table -schemas/reserved_names/tables/names/table [schemas/reserved_names/schema schemas/reserved_names/tables/kinds/table schemas/reserved_names/tables/reasons/table] 2026-10-22T19:40:00Z devin # add schemas/reserved_names/tables/names/table -schemas/reserved_names/tables/names/indexes/names_reason_idx [schemas/reserved_names/schema schemas/reserved_names/tables/names/table] 2026-10-22T19:40:00Z devin # add schemas/reserved_names/tables/names/indexes/names_reason_idx -schemas/reserved_names/procedures/reserved_by [schemas/reserved_names/schema schemas/reserved_names/tables/names/table] 2026-10-22T19:40:00Z devin # add schemas/reserved_names/procedures/reserved_by -schemas/reserved_names/procedures/is_reserved [schemas/reserved_names/schema schemas/reserved_names/procedures/reserved_by] 2026-10-22T19:40:00Z devin # add schemas/reserved_names/procedures/is_reserved -schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture [schemas/reserved_names/schema schemas/reserved_names/tables/kinds/table] 2026-10-22T19:40:00Z devin # add schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture -schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture [schemas/reserved_names/schema schemas/reserved_names/tables/reasons/table] 2026-10-22T19:40:00Z devin # add schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture -schemas/reserved_names/tables/names/fixtures/1792800000002_fixture [schemas/reserved_names/schema schemas/reserved_names/tables/names/table schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture] 2026-10-22T19:40:00Z devin # add schemas/reserved_names/tables/names/fixtures/1792800000002_fixture diff --git a/packages/reserved-names/revert/schemas/reserved_names/procedures/is_reserved.sql b/packages/reserved-names/revert/schemas/reserved_names/procedures/is_reserved.sql deleted file mode 100644 index 9f8f0378..00000000 --- a/packages/reserved-names/revert/schemas/reserved_names/procedures/is_reserved.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Revert schemas/reserved_names/procedures/is_reserved from pg - -BEGIN; - -DROP FUNCTION reserved_names.is_reserved(text, text); - -COMMIT; diff --git a/packages/reserved-names/revert/schemas/reserved_names/procedures/reserved_by.sql b/packages/reserved-names/revert/schemas/reserved_names/procedures/reserved_by.sql deleted file mode 100644 index 32c580d5..00000000 --- a/packages/reserved-names/revert/schemas/reserved_names/procedures/reserved_by.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Revert schemas/reserved_names/procedures/reserved_by from pg - -BEGIN; - -DROP FUNCTION reserved_names.reserved_by(text, text); - -COMMIT; diff --git a/packages/reserved-names/revert/schemas/reserved_names/schema.sql b/packages/reserved-names/revert/schemas/reserved_names/schema.sql deleted file mode 100644 index 583c93dc..00000000 --- a/packages/reserved-names/revert/schemas/reserved_names/schema.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Revert schemas/reserved_names/schema from pg - -BEGIN; - -DROP SCHEMA reserved_names; - -COMMIT; diff --git a/packages/reserved-names/revert/schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture.sql b/packages/reserved-names/revert/schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture.sql deleted file mode 100644 index f4e51b69..00000000 --- a/packages/reserved-names/revert/schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Revert schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture from pg - -BEGIN; - -DELETE FROM reserved_names.kinds WHERE kind IN ('subdomain', 'username', 'domain', 'slug'); - -COMMIT; diff --git a/packages/reserved-names/revert/schemas/reserved_names/tables/kinds/table.sql b/packages/reserved-names/revert/schemas/reserved_names/tables/kinds/table.sql deleted file mode 100644 index e79db39d..00000000 --- a/packages/reserved-names/revert/schemas/reserved_names/tables/kinds/table.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Revert schemas/reserved_names/tables/kinds/table from pg - -BEGIN; - -DROP TABLE reserved_names.kinds; - -COMMIT; diff --git a/packages/reserved-names/revert/schemas/reserved_names/tables/names/fixtures/1792800000002_fixture.sql b/packages/reserved-names/revert/schemas/reserved_names/tables/names/fixtures/1792800000002_fixture.sql deleted file mode 100644 index 9f766f96..00000000 --- a/packages/reserved-names/revert/schemas/reserved_names/tables/names/fixtures/1792800000002_fixture.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Revert schemas/reserved_names/tables/names/fixtures/1792800000002_fixture from pg - -BEGIN; - -DELETE FROM reserved_names.names WHERE kind = 'subdomain'; - -COMMIT; diff --git a/packages/reserved-names/revert/schemas/reserved_names/tables/names/indexes/names_reason_idx.sql b/packages/reserved-names/revert/schemas/reserved_names/tables/names/indexes/names_reason_idx.sql deleted file mode 100644 index 26b44cbd..00000000 --- a/packages/reserved-names/revert/schemas/reserved_names/tables/names/indexes/names_reason_idx.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Revert schemas/reserved_names/tables/names/indexes/names_reason_idx from pg - -BEGIN; - -DROP INDEX reserved_names.names_reason_idx; - -COMMIT; diff --git a/packages/reserved-names/revert/schemas/reserved_names/tables/names/table.sql b/packages/reserved-names/revert/schemas/reserved_names/tables/names/table.sql deleted file mode 100644 index 7e60595e..00000000 --- a/packages/reserved-names/revert/schemas/reserved_names/tables/names/table.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Revert schemas/reserved_names/tables/names/table from pg - -BEGIN; - -DROP TABLE reserved_names.names; - -COMMIT; diff --git a/packages/reserved-names/revert/schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture.sql b/packages/reserved-names/revert/schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture.sql deleted file mode 100644 index 71cfd0c3..00000000 --- a/packages/reserved-names/revert/schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Revert schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture from pg - -BEGIN; - -DELETE FROM reserved_names.reasons WHERE reason IN ('platform', 'brand', 'lookalike', 'abuse'); - -COMMIT; diff --git a/packages/reserved-names/revert/schemas/reserved_names/tables/reasons/table.sql b/packages/reserved-names/revert/schemas/reserved_names/tables/reasons/table.sql deleted file mode 100644 index 6f2d1272..00000000 --- a/packages/reserved-names/revert/schemas/reserved_names/tables/reasons/table.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Revert schemas/reserved_names/tables/reasons/table from pg - -BEGIN; - -DROP TABLE reserved_names.reasons; - -COMMIT; diff --git a/packages/reserved-names/sql/pgpm-reserved-names--0.47.5.bundle.tar.gz b/packages/reserved-names/sql/pgpm-reserved-names--0.47.5.bundle.tar.gz deleted file mode 100644 index 366a03ee..00000000 Binary files a/packages/reserved-names/sql/pgpm-reserved-names--0.47.5.bundle.tar.gz and /dev/null differ diff --git a/packages/reserved-names/sql/pgpm-reserved-names--0.47.5.sql b/packages/reserved-names/sql/pgpm-reserved-names--0.47.5.sql deleted file mode 100644 index cbb25967..00000000 --- a/packages/reserved-names/sql/pgpm-reserved-names--0.47.5.sql +++ /dev/null @@ -1,157 +0,0 @@ -\echo Use "CREATE EXTENSION pgpm-reserved-names" to load this file. \quit -CREATE SCHEMA reserved_names; - -GRANT USAGE ON SCHEMA reserved_names TO PUBLIC; - -CREATE TABLE reserved_names.kinds ( - kind text PRIMARY KEY CHECK (kind ~ '^[a-z][a-z0-9_]*$'), - description text NOT NULL -); - -COMMENT ON TABLE reserved_names.kinds IS 'Categories of names that can be reserved: subdomain, username, domain, slug, ...'; - -GRANT SELECT ON reserved_names.kinds TO PUBLIC; - -CREATE TABLE reserved_names.reasons ( - reason text PRIMARY KEY CHECK (reason ~ '^[a-z][a-z0-9_]*$'), - description text NOT NULL -); - -COMMENT ON TABLE reserved_names.reasons IS 'Why a name is reserved: platform, brand, lookalike, abuse, ...'; - -GRANT SELECT ON reserved_names.reasons TO PUBLIC; - -CREATE TABLE reserved_names.names ( - kind text NOT NULL REFERENCES reserved_names.kinds (kind), - name text NOT NULL CHECK ( - name <> '' - AND name = lower(name) - ), - match text NOT NULL DEFAULT 'exact' CHECK (match IN ('exact', 'prefix', 'suffix')), - reason text NOT NULL REFERENCES reserved_names.reasons (reason), - PRIMARY KEY (kind, name, match) -); - -COMMENT ON TABLE reserved_names.names IS 'Names nobody may claim, by kind. Changed only by migrations.'; - -COMMENT ON COLUMN reserved_names.names.name IS 'The reserved name, lowercase'; - -COMMENT ON COLUMN reserved_names.names.match IS 'exact: the name itself; prefix: every name starting with it; suffix: every name ending with it'; - -GRANT SELECT ON reserved_names.names TO PUBLIC; - -CREATE INDEX names_reason_idx ON reserved_names.names (reason); - -CREATE FUNCTION reserved_names.reserved_by( - kind text, - name text -) RETURNS SETOF reserved_names.names AS $EOFCODE$ - SELECT n.* - FROM reserved_names.names n - WHERE n.kind = pg_catalog.lower(reserved_by.kind) - AND CASE n.match - WHEN 'exact' THEN n.name = pg_catalog.lower(reserved_by.name) - WHEN 'prefix' THEN pg_catalog.starts_with(pg_catalog.lower(reserved_by.name), n.name) - WHEN 'suffix' THEN pg_catalog.right(pg_catalog.lower(reserved_by.name), pg_catalog.length(n.name)) = n.name - END; -$EOFCODE$ LANGUAGE sql STABLE; - -COMMENT ON FUNCTION reserved_names.reserved_by(text, text) IS 'The entries (with their reason) that reserve name for kind; empty when it is free'; - -GRANT EXECUTE ON FUNCTION reserved_names.reserved_by(text, text) TO PUBLIC; - -CREATE FUNCTION reserved_names.is_reserved( - kind text, - name text -) RETURNS boolean AS $EOFCODE$ - SELECT EXISTS (SELECT 1 FROM reserved_names.reserved_by(is_reserved.kind, is_reserved.name)); -$EOFCODE$ LANGUAGE sql STABLE; - -COMMENT ON FUNCTION reserved_names.is_reserved(text, text) IS 'True when name (any case) is reserved for kind'; - -GRANT EXECUTE ON FUNCTION reserved_names.is_reserved(text, text) TO PUBLIC; - -INSERT INTO reserved_names.kinds ( - kind, - description -) VALUES - ('subdomain', 'A label under a shared domain, like login in login.example.com'), - ('username', 'A person''s handle'), - ('domain', 'A whole domain name, like example.com'), - ('slug', 'A name in a URL path, like an organization or app slug'); - -INSERT INTO reserved_names.reasons ( - reason, - description -) VALUES - ('platform', 'Reads as the platform''s own (login, admin, status, ...)'), - ('brand', 'Our brand or product names'), - ('lookalike', 'Can be made to look like another name, e.g. punycode'), - ('abuse', 'Offensive or used for abuse'); - -INSERT INTO reserved_names.names ( - kind, - name, - match, - reason -) VALUES - ('subdomain', 'www', 'exact', 'platform'), - ('subdomain', 'api', 'exact', 'platform'), - ('subdomain', 'auth', 'exact', 'platform'), - ('subdomain', 'login', 'exact', 'platform'), - ('subdomain', 'logout', 'exact', 'platform'), - ('subdomain', 'signin', 'exact', 'platform'), - ('subdomain', 'signup', 'exact', 'platform'), - ('subdomain', 'register', 'exact', 'platform'), - ('subdomain', 'admin', 'exact', 'platform'), - ('subdomain', 'administrator', 'exact', 'platform'), - ('subdomain', 'root', 'exact', 'platform'), - ('subdomain', 'app', 'exact', 'platform'), - ('subdomain', 'apps', 'exact', 'platform'), - ('subdomain', 'dashboard', 'exact', 'platform'), - ('subdomain', 'console', 'exact', 'platform'), - ('subdomain', 'account', 'exact', 'platform'), - ('subdomain', 'accounts', 'exact', 'platform'), - ('subdomain', 'billing', 'exact', 'platform'), - ('subdomain', 'pay', 'exact', 'platform'), - ('subdomain', 'payments', 'exact', 'platform'), - ('subdomain', 'checkout', 'exact', 'platform'), - ('subdomain', 'support', 'exact', 'platform'), - ('subdomain', 'help', 'exact', 'platform'), - ('subdomain', 'status', 'exact', 'platform'), - ('subdomain', 'docs', 'exact', 'platform'), - ('subdomain', 'mail', 'exact', 'platform'), - ('subdomain', 'email', 'exact', 'platform'), - ('subdomain', 'smtp', 'exact', 'platform'), - ('subdomain', 'imap', 'exact', 'platform'), - ('subdomain', 'ftp', 'exact', 'platform'), - ('subdomain', 'ns', 'exact', 'platform'), - ('subdomain', 'ns1', 'exact', 'platform'), - ('subdomain', 'ns2', 'exact', 'platform'), - ('subdomain', 'mx', 'exact', 'platform'), - ('subdomain', 'cdn', 'exact', 'platform'), - ('subdomain', 'static', 'exact', 'platform'), - ('subdomain', 'assets', 'exact', 'platform'), - ('subdomain', 'files', 'exact', 'platform'), - ('subdomain', 'storage', 'exact', 'platform'), - ('subdomain', 'media', 'exact', 'platform'), - ('subdomain', 'ws', 'exact', 'platform'), - ('subdomain', 'wss', 'exact', 'platform'), - ('subdomain', 'graphql', 'exact', 'platform'), - ('subdomain', 'modules', 'exact', 'platform'), - ('subdomain', 'agent', 'exact', 'platform'), - ('subdomain', 'compute', 'exact', 'platform'), - ('subdomain', 'machines', 'exact', 'platform'), - ('subdomain', 'cluster', 'exact', 'platform'), - ('subdomain', 'migrate', 'exact', 'platform'), - ('subdomain', 'internal', 'exact', 'platform'), - ('subdomain', 'system', 'exact', 'platform'), - ('subdomain', 'platform', 'exact', 'platform'), - ('subdomain', 'security', 'exact', 'platform'), - ('subdomain', 'sso', 'exact', 'platform'), - ('subdomain', 'oauth', 'exact', 'platform'), - ('subdomain', 'id', 'exact', 'platform'), - ('subdomain', 'identity', 'exact', 'platform'), - ('subdomain', 'verify', 'exact', 'platform'), - ('subdomain', 'secure', 'exact', 'platform'), - ('subdomain', 'xn--', 'prefix', 'lookalike'); \ No newline at end of file diff --git a/packages/reserved-names/verify/schemas/reserved_names/procedures/is_reserved.sql b/packages/reserved-names/verify/schemas/reserved_names/procedures/is_reserved.sql deleted file mode 100644 index bae6eedb..00000000 --- a/packages/reserved-names/verify/schemas/reserved_names/procedures/is_reserved.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Verify schemas/reserved_names/procedures/is_reserved on pg - -BEGIN; - -SELECT assert_function('reserved_names.is_reserved(text, text)'::regprocedure); - -ROLLBACK; diff --git a/packages/reserved-names/verify/schemas/reserved_names/procedures/reserved_by.sql b/packages/reserved-names/verify/schemas/reserved_names/procedures/reserved_by.sql deleted file mode 100644 index d155b62b..00000000 --- a/packages/reserved-names/verify/schemas/reserved_names/procedures/reserved_by.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Verify schemas/reserved_names/procedures/reserved_by on pg - -BEGIN; - -SELECT assert_function('reserved_names.reserved_by(text, text)'::regprocedure); - -ROLLBACK; diff --git a/packages/reserved-names/verify/schemas/reserved_names/schema.sql b/packages/reserved-names/verify/schemas/reserved_names/schema.sql deleted file mode 100644 index 6e605ce0..00000000 --- a/packages/reserved-names/verify/schemas/reserved_names/schema.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Verify schemas/reserved_names/schema on pg - -BEGIN; - -SELECT assert_schema('reserved_names'::regnamespace); - -ROLLBACK; diff --git a/packages/reserved-names/verify/schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture.sql b/packages/reserved-names/verify/schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture.sql deleted file mode 100644 index f7fad434..00000000 --- a/packages/reserved-names/verify/schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Verify schemas/reserved_names/tables/kinds/fixtures/1792800000000_fixture on pg - -BEGIN; - -SELECT 1/count(*) FROM reserved_names.kinds WHERE kind = 'subdomain'; - -ROLLBACK; diff --git a/packages/reserved-names/verify/schemas/reserved_names/tables/kinds/table.sql b/packages/reserved-names/verify/schemas/reserved_names/tables/kinds/table.sql deleted file mode 100644 index bec62dd1..00000000 --- a/packages/reserved-names/verify/schemas/reserved_names/tables/kinds/table.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Verify schemas/reserved_names/tables/kinds/table on pg - -BEGIN; - -SELECT assert_table('reserved_names.kinds'::regclass); - -ROLLBACK; diff --git a/packages/reserved-names/verify/schemas/reserved_names/tables/names/fixtures/1792800000002_fixture.sql b/packages/reserved-names/verify/schemas/reserved_names/tables/names/fixtures/1792800000002_fixture.sql deleted file mode 100644 index 87b28e70..00000000 --- a/packages/reserved-names/verify/schemas/reserved_names/tables/names/fixtures/1792800000002_fixture.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Verify schemas/reserved_names/tables/names/fixtures/1792800000002_fixture on pg - -BEGIN; - -SELECT 1/count(*) FROM reserved_names.names WHERE kind = 'subdomain' AND name = 'login'; - -ROLLBACK; diff --git a/packages/reserved-names/verify/schemas/reserved_names/tables/names/indexes/names_reason_idx.sql b/packages/reserved-names/verify/schemas/reserved_names/tables/names/indexes/names_reason_idx.sql deleted file mode 100644 index 426d1c48..00000000 --- a/packages/reserved-names/verify/schemas/reserved_names/tables/names/indexes/names_reason_idx.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Verify schemas/reserved_names/tables/names/indexes/names_reason_idx on pg - -BEGIN; - -SELECT assert_index('reserved_names.names_reason_idx'::regclass, 'reserved_names.names'::regclass); - -ROLLBACK; diff --git a/packages/reserved-names/verify/schemas/reserved_names/tables/names/table.sql b/packages/reserved-names/verify/schemas/reserved_names/tables/names/table.sql deleted file mode 100644 index 167030de..00000000 --- a/packages/reserved-names/verify/schemas/reserved_names/tables/names/table.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Verify schemas/reserved_names/tables/names/table on pg - -BEGIN; - -SELECT assert_table('reserved_names.names'::regclass); - -ROLLBACK; diff --git a/packages/reserved-names/verify/schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture.sql b/packages/reserved-names/verify/schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture.sql deleted file mode 100644 index 83280742..00000000 --- a/packages/reserved-names/verify/schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Verify schemas/reserved_names/tables/reasons/fixtures/1792800000001_fixture on pg - -BEGIN; - -SELECT 1/count(*) FROM reserved_names.reasons WHERE reason = 'platform'; - -ROLLBACK; diff --git a/packages/reserved-names/verify/schemas/reserved_names/tables/reasons/table.sql b/packages/reserved-names/verify/schemas/reserved_names/tables/reasons/table.sql deleted file mode 100644 index 7481a674..00000000 --- a/packages/reserved-names/verify/schemas/reserved_names/tables/reasons/table.sql +++ /dev/null @@ -1,7 +0,0 @@ --- Verify schemas/reserved_names/tables/reasons/table on pg - -BEGIN; - -SELECT assert_table('reserved_names.reasons'::regclass); - -ROLLBACK; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b4bbb30..92051e6a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -338,16 +338,6 @@ importers: specifier: ^5 version: 5.8.0(@dataplan/json@1.0.0(grafast@1.0.2(graphql@16.13.0)))(@dataplan/pg@1.0.3(@dataplan/json@1.0.0(grafast@1.0.2(graphql@16.13.0)))(grafast@1.0.2(graphql@16.13.0))(graphile-config@1.0.1)(graphql@16.13.0)(pg-sql2@5.0.1)(pg@8.22.0))(@types/node@22.19.17)(grafserv@1.0.0(@types/node@22.19.17)(grafast@1.0.2(graphql@16.13.0))(graphile-config@1.0.1)(graphql@16.13.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(use-sync-external-store@1.6.0(react@19.2.5))(ws@8.20.0))(graphile-build@5.0.2(grafast@1.0.2(graphql@16.13.0))(graphile-config@1.0.1)(graphql@16.13.0))(pg-sql2@5.0.1)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tamedevil@0.1.1)(use-sync-external-store@1.6.0(react@19.2.5))(ws@8.20.0) - packages/reserved-names: - dependencies: - "@pgpm/verify": - specifier: workspace:* - version: link:../verify - devDependencies: - pgpm: - specifier: ^5 - version: 5.8.0(@dataplan/json@1.0.0(grafast@1.0.2(graphql@16.13.0)))(@dataplan/pg@1.0.3(@dataplan/json@1.0.0(grafast@1.0.2(graphql@16.13.0)))(grafast@1.0.2(graphql@16.13.0))(graphile-config@1.0.1)(graphql@16.13.0)(pg-sql2@5.0.1)(pg@8.22.0))(@types/node@22.19.17)(grafserv@1.0.0(@types/node@22.19.17)(grafast@1.0.2(graphql@16.13.0))(graphile-config@1.0.1)(graphql@16.13.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(use-sync-external-store@1.6.0(react@19.2.5))(ws@8.20.0))(graphile-build@5.0.2(grafast@1.0.2(graphql@16.13.0))(graphile-config@1.0.1)(graphql@16.13.0))(pg-sql2@5.0.1)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tamedevil@0.1.1)(use-sync-external-store@1.6.0(react@19.2.5))(ws@8.20.0) - packages/stamps: dependencies: "@pgpm/jwt-claims":