diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml
new file mode 100644
index 00000000000..bacadccbf1e
--- /dev/null
+++ b/.github/workflows/mirror.yml
@@ -0,0 +1,33 @@
+name: Mirror Image
+
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ description: "Image tag"
+ required: true
+ type: string
+
+jobs:
+ mirror:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ steps:
+ - uses: docker/login-action@v2
+ with:
+ registry: public.ecr.aws
+ username: ${{ secrets.PROD_ACCESS_KEY_ID }}
+ password: ${{ secrets.PROD_SECRET_ACCESS_KEY }}
+ - uses: docker/login-action@v2
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - uses: akhilerm/tag-push-action@v2.1.0
+ with:
+ src: docker.io/supabase/studio:${{ inputs.version }}
+ dst: |
+ public.ecr.aws/supabase/studio:${{ inputs.version }}
+ ghcr.io/supabase/studio:${{ inputs.version }}
diff --git a/.github/workflows/publish_image.yml b/.github/workflows/publish_image.yml
index 6106dad6b42..fb21fd49d43 100644
--- a/.github/workflows/publish_image.yml
+++ b/.github/workflows/publish_image.yml
@@ -16,13 +16,17 @@ on:
jobs:
publish:
runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
steps:
- id: meta
uses: docker/metadata-action@v4
with:
images: |
supabase/studio
- public.ecr.aws/t3w2s2c9/studio
+ public.ecr.aws/supabase/studio
+ ghcr.io/supabase/studio
flavor: |
latest=false
tags: |
@@ -49,6 +53,13 @@ jobs:
username: ${{ secrets.PROD_ACCESS_KEY_ID }}
password: ${{ secrets.PROD_SECRET_ACCESS_KEY }}
+ - name: Login to GHCR
+ uses: docker/login-action@v2
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
- uses: docker/build-push-action@v3
with:
push: true
diff --git a/DEVELOPERS.md b/DEVELOPERS.md
index 585e7359e3d..d4a62cd88f9 100644
--- a/DEVELOPERS.md
+++ b/DEVELOPERS.md
@@ -75,7 +75,7 @@ Then visit, and edit, any of the following sites:
| ---------------------------------------------- | -------------- | ---------- | ------------------------------------ | ------------------------ |
| [supabase.com](https://supabase.com) | `/apps/www` | www | The main website | http://localhost:3000 |
| [app.supabase.com](https://app.supabase.com) | `/studio` | studio | Studio dashboard | http://localhost:8082 |
-| [supabase.com/docs](https://supabase.com/docs) | `/apps/docs` | docs | Guides and Reference (Next.js based) | http://localhost:3001 |
+| [supabase.com/docs](https://supabase.com/docs) | `/apps/docs` | docs | Guides and Reference (Next.js based) | http://localhost:3001/docs |
#### Running sites individually
diff --git a/README.md b/README.md
index c24e86943fa..4c35921e1a5 100644
--- a/README.md
+++ b/README.md
@@ -58,7 +58,7 @@ Supabase is a combination of open source tools. We’re building the features of
Supabase is a [hosted platform](https://app.supabase.com). You can sign up and start using Supabase without installing anything.
You can also [self-host](https://supabase.com/docs/guides/hosting/overview) and [develop locally](https://supabase.com/docs/guides/local-development).
-
+
- [PostgreSQL](https://www.postgresql.org/) is an object-relational database system with over 30 years of active development that has earned it a strong reputation for reliability, feature robustness, and performance.
- [Realtime](https://github.com/supabase/realtime) is an Elixir server that allows you to listen to PostgreSQL inserts, updates, and deletes using websockets. Realtime polls Postgres' built-in replication functionality for database changes, converts changes to JSON, then broadcasts the JSON over websockets to authorized clients.
diff --git a/apps/docs/components/Navigation/Navigation.constants.ts b/apps/docs/components/Navigation/Navigation.constants.ts
index 5bfb8aa40df..3c407085da2 100644
--- a/apps/docs/components/Navigation/Navigation.constants.ts
+++ b/apps/docs/components/Navigation/Navigation.constants.ts
@@ -237,7 +237,7 @@ export const menuItems: NavMenu = {
items: [
{ name: 'Overview', url: '/guides/realtime', items: [] },
{ name: 'Quickstart', url: '/guides/realtime/quickstart', items: [] },
- { name: 'Postgres CDC', url: '/guides/realtime/postgres-cdc', items: [] },
+ { name: 'Postgres Changes', url: '/guides/realtime/postgres-changes', items: [] },
{ name: 'Rate Limits', url: '/guides/realtime/rate-limits', items: [] },
],
},
diff --git a/apps/docs/pages/features.mdx b/apps/docs/pages/features.mdx
index 06152162e48..22a1dfd567a 100755
--- a/apps/docs/pages/features.mdx
+++ b/apps/docs/pages/features.mdx
@@ -92,7 +92,7 @@ Fast GraphQL APIs using our custom Postgres GraphQL extension. [Docs](/docs/guid
### Realtime Database changes
-Receive your database changes through websockets. [Docs](/docs/guides/realtime/postgres-cdc).
+Receive your database changes through websockets. [Docs](/docs/guides/realtime/postgres-changes).
### User Broadcasting
@@ -156,7 +156,7 @@ Both Postgres and the Supabase Platform are production-ready. Some tools we offe
| Database | Point-in-Time Recovery | `alpha` |
| Database | Vault | `alpha` |
| Studio | | `GA` |
-| Realtime | Postgres CDC | `GA` |
+| Realtime | Postgres Changes | `GA` |
| Realtime | Broadcast | `beta` |
| Realtime | Presence | `beta` |
| Storage | Backend (S3) | `GA` |
diff --git a/apps/docs/pages/guides/database/extensions/pgnet.mdx b/apps/docs/pages/guides/database/extensions/pgnet.mdx
index afaa24a8378..f9b99c7e018 100644
--- a/apps/docs/pages/guides/database/extensions/pgnet.mdx
+++ b/apps/docs/pages/guides/database/extensions/pgnet.mdx
@@ -8,7 +8,7 @@ export const meta = {
-The pg_net API is in beta. Functions signatures may change.
+The pg_net API is in alpha. Functions signatures may change.
@@ -150,102 +150,6 @@ request_id
After triggering `http_post`, use [`http_get_result`](#http_get_result) to get the result of the request.
-## `http_collect_response` [#http_collect_response]
-
-Given a `request_id` reference, retrieves the response.
-
-When `async:=false` is set it is recommended that [statement_timeout](https://www.postgresql.org/docs/13/runtime-config-client.html) is set for the maximum amount of time the caller is willing to wait in case the response is slow to populate.
-
-### Signature
-
-
-
-This is a Postgres SECURITY DEFINER function
-
-
-
-```sql
-net.http_collect_response(
- -- request_id reference
- request_id bigint,
- -- when `true`, return immediately. when `false` wait for the request to complete before returning
- async bool default true
-)
- -- http response composite wrapped in a result type
- returns net.http_response_result
-
- strict
- volatile
- parallel safe
-```
-
-### Usage
-
-
-
-`net.http_collect_response` must be in a separate transaction from the calls to `net.http_`
-
-
-
-```sql
-select
- net.http_post(
- url:='https://httpbin.org/post',
- body:='{"hello": "world"}'::jsonb
- ) as request_id;
-request_id
-----------
- 1
-(1 row)
-
-select * from net.http_collect_response(1, async:=false);
-status | message | response
---------+---------+----------
-SUCCESS ok (
- status_code := 200,
- headers := '{"date": ...}',
- body := '{"args": ...}'
- )::net.http_response_result
-
-
-select
- (response).body::json
-from
- net.http_collect_response(request_id:=1);
- body
--------------------------------------------------------------------
- {
- "args": {},
- "data": "{\"hello\": \"world\"}",
- "files": {},
- "form": {},
- "headers": {
- "Accept": "*/*",
- "Content-Length": "18",
- "Content-Type": "application/json",
- "Host": "httpbin.org",
- "User-Agent": "pg_net/0.2",
- "X-Amzn-Trace-Id": "Root=1-61031a5c-7e1afeae69bffa8614d8e48e"
- },
- "json": {
- "hello": "world"
- },
- "origin": "135.63.38.488",
- "url": "https://httpbin.org/post"
- }
-(1 row)
-```
-
-Where `response` is a composite:
-
-```sql
-status_code integer
-headers jsonb
-body text
-```
-
-Possible values for `net.http_response_result.status` are `('PENDING', 'SUCCESS', 'ERROR')`
-
## Resources
- Source code: [github.com/supabase/pg_net](https://github.com/supabase/pg_net/)
diff --git a/apps/docs/pages/guides/functions/quickstart.mdx b/apps/docs/pages/guides/functions/quickstart.mdx
index 963305181a3..55b9ed617c6 100644
--- a/apps/docs/pages/guides/functions/quickstart.mdx
+++ b/apps/docs/pages/guides/functions/quickstart.mdx
@@ -106,7 +106,7 @@ You should see the response `{ "message":"Hello Functions!" }`.
Implementation details
-- All Edge Functions are `POST` requests.
+- Edge Functions don't serve HTML content (`GET` requests that return `text/html` are rewritten to `text/plain`).
- The `Authorization` header is required. You can use either the `ANON` key, the `SERVICE_ROLE` key, or a logged-in user's JWT.
- The Function is proxied through the local API (`http://localhost:54321`)
diff --git a/apps/docs/pages/guides/integrations/zuplo.mdx b/apps/docs/pages/guides/integrations/zuplo.mdx
index c4eb7cc98e4..06b621b5b47 100644
--- a/apps/docs/pages/guides/integrations/zuplo.mdx
+++ b/apps/docs/pages/guides/integrations/zuplo.mdx
@@ -30,7 +30,7 @@ Manually enter a couple of rows of data, so that we have something to read from
## The `Get all` reviews route in Zuplo
-Login to Zuplo at [portal.zuplo.com](https://portal.zuplo.com] and create a new project in Zuplo - I went with `supabase-ski-reviews`.
+Login to Zuplo at [portal.zuplo.com](https://portal.zuplo.com) and create a new project in Zuplo - I went with `supabase-ski-reviews`.
Select the **File** tab and choose **Routes**. Add your first route with the following settings:
diff --git a/apps/docs/pages/guides/platform/custom-domains.mdx b/apps/docs/pages/guides/platform/custom-domains.mdx
index 36565487f59..0ff3d80bb49 100644
--- a/apps/docs/pages/guides/platform/custom-domains.mdx
+++ b/apps/docs/pages/guides/platform/custom-domains.mdx
@@ -12,7 +12,7 @@ Custom Domains are currently in beta, and are being slowly made available to pro
-Custom domains allow you to present a branded experience to your users. You can also use a subdomain for the purposes of this guide.
+Custom domains allow you to present a branded experience to your users. Currently, you must use a subdomain (e.g., `api.example.com`, rather than `example.com`) for the purposes of this guide.
To get started:
diff --git a/apps/docs/pages/guides/realtime.mdx b/apps/docs/pages/guides/realtime.mdx
index acf13a0f57b..e6b8ce7e283 100644
--- a/apps/docs/pages/guides/realtime.mdx
+++ b/apps/docs/pages/guides/realtime.mdx
@@ -3,7 +3,7 @@ import Layout from '~/layouts/DefaultGuideLayout'
export const meta = {
id: 'realtime',
title: 'Realtime',
- description: 'Supabase Realtime with Broadcast, Presence, and Postgres CDC.',
+ description: 'Supabase Realtime with Broadcast, Presence, and Postgres Changes.',
sidebar_label: 'Overview',
}
@@ -11,11 +11,11 @@ Supabase provides a globally distributed cluster of [Realtime](https://github.co
- [Broadcast](#broadcast): Send ephemeral messages from client to clients with low latency.
- [Presence](#presence): Track and synchronize shared state between clients.
-- [Postgres CDC](#postgres-cdc): Listen to Postgres database changes and send them to authorized clients.
+- [Postgres Changes](#postgres-changes): Listen to Postgres database changes and send them to authorized clients.
A [channel](https://hexdocs.pm/phoenix/channels.html) is the basic building block of Realtime and narrows the scope of data flow to subscribed clients. You can think of a channel as a chatroom where participants are able to see who's online and send and receive messages; similar to a Discord or Slack channel.
-All clients can connect to a channel and take advantage of the built-in features, Broadcast and Presence, while extenstions, like Postgres CDC, must be enabled prior to use.
+All clients can connect to a channel and take advantage of the built-in features, Broadcast and Presence, while extenstions, like Postgres Changes, must be enabled prior to use.
## Broadcast
@@ -37,9 +37,9 @@ Clients are free to come-and-go as they please, and as long as they are all subs
The neat thing about Presence is that if a client is suddenly disconnected (for example, they go offline), their state will be automatically removed from the shared state. If you've ever tried to build an “I'm online” feature which handles unexpected disconnects, you'll appreciate how useful this is.
-## Postgres CDC
+## Postgres Changes
-Postgres Change Data Capture (CDC) enables you to listen to database changes and have them broadcast to authorized clients based on [Row Level Security (RLS)](/docs/guides/auth/row-level-security) policies.
+Postgres Changes enable you to listen to database changes and have them broadcast to authorized clients based on [Row Level Security (RLS)](/docs/guides/auth/row-level-security) policies.
This works by Realtime polling your database's logical replication slot for changes, passing those changes to the [apply_rls](https://github.com/supabase/walrus#reading-wal) SQL function to determine which clients have permission, and then using Broadcast to send those changes to clients.
diff --git a/apps/docs/pages/guides/realtime/postgres-cdc.mdx b/apps/docs/pages/guides/realtime/postgres-changes.mdx
similarity index 83%
rename from apps/docs/pages/guides/realtime/postgres-cdc.mdx
rename to apps/docs/pages/guides/realtime/postgres-changes.mdx
index c8d20133f3a..79a76e884b2 100644
--- a/apps/docs/pages/guides/realtime/postgres-cdc.mdx
+++ b/apps/docs/pages/guides/realtime/postgres-changes.mdx
@@ -1,18 +1,18 @@
import Layout from '~/layouts/DefaultGuideLayout'
export const meta = {
- id: 'postgres-cdc',
- title: 'Postgres CDC',
- description: "Getting started with Realtime's Postgres CDC feature",
+ id: 'postgres-changes',
+ title: 'Postgres Changes',
+ description: "Getting started with Realtime's Postgres Changes feature",
}
-Realtime's Postgres Change Data Capture (CDC) feature listens for database changes and sends them to clients. Clients are required to subscribe with a JWT dictating which changes they are allowed to receive based on the database's [Row Level Security](/docs/guides/auth/row-level-security).
+Realtime's Postgres Changes feature listens for database changes and sends them to clients. Clients are required to subscribe with a JWT dictating which changes they are allowed to receive based on the database's [Row Level Security](/docs/guides/auth/row-level-security).
Anyone with access to a valid JWT signed with the project's JWT secret is able to listen to your database's changes, unless tables have [Row Level Security](/docs/guides/auth/row-level-security) enabled and policies in place.
Clients can choose to receive `INSERT`, `UPDATE`, `DELETE`, or `*` (all) changes for all changes in a schema, a table in a schema, or a column's value in a table. Your clients should only listen to tables in the `public` schema and you must first enable the tables you want your clients to listen to.
-Postgres CDC works out of the box for tables in the `public` schema. You can listen to tables in your private schemas by granting table `SELECT` permissions to the database role found in your access token. You can run a query similar to the following:
+Postgres Changes works out of the box for tables in the `public` schema. You can listen to tables in your private schemas by granting table `SELECT` permissions to the database role found in your access token. You can run a query similar to the following:
```sql
GRANT SELECT ON "private_schema"."table" TO authenticated;
diff --git a/apps/docs/pages/guides/realtime/quickstart.mdx b/apps/docs/pages/guides/realtime/quickstart.mdx
index 02bc5b9177b..5d384d5f874 100644
--- a/apps/docs/pages/guides/realtime/quickstart.mdx
+++ b/apps/docs/pages/guides/realtime/quickstart.mdx
@@ -7,7 +7,7 @@ export const meta = {
sidebar_label: 'Quickstart',
}
-Learn how to build [multiplayer.dev](https://multiplayer.dev), a collaborative app that demonstrates Broadcast, Presence, and Postgres CDC using [Realtime](/docs/guides/realtime).
+Learn how to build [multiplayer.dev](https://multiplayer.dev), a collaborative app that demonstrates Broadcast, Presence, and Postgres Changes using [Realtime](/docs/guides/realtime).
diff --git a/apps/docs/public/sitemap.xml b/apps/docs/public/sitemap.xml
index 6d2c085106e..246445d80af 100644
--- a/apps/docs/public/sitemap.xml
+++ b/apps/docs/public/sitemap.xml
@@ -799,7 +799,7 @@
- https://supabase.com/docs/guides/realtime/postgres-cdc
+ https://supabase.com/docs/guides/realtime/postgres-changesweekly0.5
diff --git a/apps/www/_blog/2022-12-01-transparent-column-encryption-with-postgres.mdx b/apps/www/_blog/2022-12-01-transparent-column-encryption-with-postgres.mdx
index 75c05cf7f08..260719c186f 100644
--- a/apps/www/_blog/2022-12-01-transparent-column-encryption-with-postgres.mdx
+++ b/apps/www/_blog/2022-12-01-transparent-column-encryption-with-postgres.mdx
@@ -18,7 +18,7 @@ To understand how TCE works, let's first do a deep-dive into an important encryp
- This post is a sneak peek of a big feature we are shipping on LW6. To not miss a thing, get your ticket for [Supabase Launch Week 6!](https://supabase.com/launch-week).
+This post is a sneak peek of a big feature we are shipping on LW6. To not miss a thing, get your ticket for [Supabase Launch Week 6!](https://supabase.com/launch-week).
@@ -28,23 +28,23 @@ The current state-of-the-art in encryption libraries is [libsodium](https://doc.
**libsodium** offers a range of APIs for authenticated secret and public key encryption, key derivation, encrypted streaming, [AEAD](https://en.wikipedia.org/wiki/Authenticated_encryption), various forms of hashing, and much more.
-This powerful API is available to PostgreSQL using the [**pgsodium**](https://github.com/michelp/pgsodium) extension. **pgsodium** provides all the functionality of the full **libsodium** API, but previously it required developers to set up database encryption themselves, which remained a challenge even for those familiar with database administration.
+This powerful API is available to PostgreSQL using the [**pgsodium**](https://github.com/michelp/pgsodium) extension. **pgsodium** provides all the functionality of the full **libsodium** API, but previously it required developers to set up database encryption themselves, which remained a challenge even for those familiar with database administration.
-To solve this problem, **pgsodium** now has a full key management API, primarily via the table `pgsodium.key` and the `pgsodium.create_key()` function. This key table contains no raw keys, but instead uses libsodium Key IDs to derive keys that are used internally for encryption. A [key derivation function](https://libsodium.gitbook.io/doc/key_derivation) is used with an internal root key that is unavailable to SQL and not stored in the database, but rather managed by you externally using flexible scripts, or by Supabase automatically as part of our service offering.
+To solve this problem, **pgsodium** now has a full key management API, primarily via the table `pgsodium.key` and the `pgsodium.create_key()` function. This key table contains no raw keys, but instead uses libsodium Key IDs to derive keys that are used internally for encryption. A [key derivation function](https://libsodium.gitbook.io/doc/key_derivation) is used with an internal root key that is unavailable to SQL and not stored in the database, but rather managed by you externally using flexible scripts, or by Supabase automatically as part of our service offering.
-The simplest way to use **pgsodium** to encrypt and decrypt data is to first create a ******Key ID******. Valid Key IDs are stored in pgsodium in a special extension table, and they can be created using the `pgsodium.create_key()` function. This function takes a number of arguments depending on how it's used, but the simplest case is to create a new key with no arguments:
+The simplest way to use **pgsodium** to encrypt and decrypt data is to first create a **Key ID**. Valid Key IDs are stored in pgsodium in a special extension table, and they can be created using the `pgsodium.create_key()` function. This function takes a number of arguments depending on how it's used, but the simplest case is to create a new key with no arguments:
```sql
select * from pgsodium.create_key();
-[ RECORD 1 ]---+-------------------------------------
id | eaa20d8c-c77c-4985-9f73-2a5f5d1f1e6d
-name |
+name |
status | valid
key_type | aead-det
key_id | 2
key_context | \x7067736f6469756d
created | 2022-11-13 21:19:35.765823+00
-expires |
+expires |
associated_data |
```
@@ -65,13 +65,13 @@ This produces the following encrypted “ciphertext” using the `aead-det` algo
crypto_aead_det_encrypt | \\x099baa820250d7375ed141f8f1936af384bc229f3de1010a6eff6ffdaf3998baffbae75b5cd83d1c469407ff2d3764a428b742
```
-Now to decrypt the ciphertext, pass it to the decryption function *with the same Key ID*:
+Now to decrypt the ciphertext, pass it to the decryption function _with the same Key ID_:
```sql
-select *
+select *
from convert_from(pgsodium.crypto_aead_det_decrypt (
- '\\x099baa820250d7375ed141f8f1936af384bc229f3de1010a6eff6ffdaf3998baffbae75b5cd83d1c469407ff2d3764a428b742',
- 'this is associated data',
+ '\\x099baa820250d7375ed141f8f1936af384bc229f3de1010a6eff6ffdaf3998baffbae75b5cd83d1c469407ff2d3764a428b742',
+ 'this is associated data',
'eaa20d8c-c77c-4985-9f73-2a5f5d1f1e6d'::uuid
), 'utf8');
```
@@ -83,24 +83,24 @@ Which recovers the original “plaintext” message:
convert_from | this is the message
```
-In the above example, there is *no raw key* like shown in the pgcrypto example above, only a Key ID which is used to derive the key used to encrypt the message and authenticate it with the associated data. In fact, it is impossible for a SQL user to derive the key used above, and if the Key ID is stored, then no decrypted information will leak into backups, disk storage, or the database WAL stream.
+In the above example, there is _no raw key_, only a Key ID which is used to derive the key used to encrypt the message and authenticate it with the associated data. In fact, it is impossible for a SQL user to derive the key used above, and if the Key ID is stored, then no encryption keys or decrypted information will leak into backups, disk storage, or the database WAL stream.
## Transparent Column Encryption
-As of **pgsodium** 3.0.0 and up, the extension offers a simple and declarative Transparent Column Encryption feature (TCE). This feature is now shipped with all Supabase projects. TCE allows you to specify encrypted columns within a table and generates a new view that “wraps” that table to decrypt the contents.
+As of **pgsodium** 3.0.0 and up, the extension offers a simple and declarative Transparent Column Encryption feature (TCE). This feature is now shipped with all Supabase projects. TCE allows you to specify encrypted columns within a table and generates a new view that “wraps” that table to decrypt the contents.
-TCE works using two dynamically generated objects for tables that contain encrypted columns:
+TCE works using two dynamically generated objects for tables that contain encrypted columns:
- an `INSERT UPDATE` trigger that encrypts data when it is inserted or modified
- a view that is created to wrap the table to decrypt the data when it is accessed
-To “transparently” decrypt the table, access the dynamically generated view *instead of the table*. For every encrypted column in the table, the view will have an additional decrypted column that shows the decrypted result.
+To “transparently” decrypt the table, access the dynamically generated view _instead of the table_. For every encrypted column in the table, the view will have an additional decrypted column that shows the decrypted result.
-It's worth noting at this point that sometimes there is some confusion about handling encrypted data with TCE. The `T` stands for ***********Transparent*********** which means, you can always see decrypted data through the view, where the decrypted data can't be see is when stored on disk, or in pg_dumps, backups, WAL streams, etc. This is often called ******************Encryption At Rest****************** and is one layer in many that may be used to encrypt and protect your data.
+It's worth noting at this point that sometimes there is some confusion about handling encrypted data with TCE. The `T` stands for **Transparent** which means, you can always see decrypted data through the view, where the decrypted data can't be see is when stored on disk, or in pg_dumps, backups, WAL streams, etc. This is often called **Encryption At Rest** and is one layer in many that may be used to encrypt and protect your data.
-Often Transparent encryption is understood to be “Transparent Disk Encryption” or “Full Disk Encryption”, this is where a drive is encrypted but reading and writing that drive is decrypted. TCE is similar to this, where data on disk is encrypted, but it is more fine grained, only particular columns are encrypted. The data is also encrypted in the sense that the table stored on disk contains encrypted data, without the view or the key, pg_dumps and backups still contain encrypted data, this is not possible with disk-only encryption.
+Often Transparent encryption is understood to be “Transparent Disk Encryption” or “Full Disk Encryption”, this is where a drive is encrypted but reading and writing that drive is decrypted. TCE is similar to this, where data on disk is encrypted, but it is more fine grained, only particular columns are encrypted. The data is also encrypted in the sense that the table stored on disk contains encrypted data, without the view or the key, pg_dumps and backups still contain encrypted data, this is not possible with disk-only encryption.
-For the moment TCE only works for columns of type `text` (or types castable to `text` like `json`). Soon we will also support `bytea` and possibly more as use cases and tests get better.
+For the moment TCE only works for columns of type `text` (or types castable to `text` like `json`). Soon we will also support `bytea` and possibly more as use cases and tests get better.
TCE uses one of PostgreSQL's lesser-known features: [`SECURITY LABEL`](https://www.postgresql.org/docs/current/sql-security-label.html). A security label can be thought of as a simple label which is attached to an object (a table, column, etc). Each label is scoped to an extension and that extension can provide security features depending on the label.
@@ -127,7 +127,7 @@ SECURITY LABEL FOR pgsodium
IS 'ENCRYPT WITH KEY ID e348034b-3f07-4878-aad6-000511d12826';
```
-The advantage of this approach is simplicity - the user creates one key and labels a column with it. The cryptographic algorithm for this approach uses a *nonceless* encryption algorithm called `crypto_aead_det_xchacha20()`. This algorithm is written by the author of libsodium and can be found [here](https://github.com/jedisct1/libsodium-xchacha20-siv).
+The advantage of this approach is simplicity - the user creates one key and labels a column with it. The cryptographic algorithm for this approach uses a _nonceless_ encryption algorithm called `crypto_aead_det_xchacha20()`. This algorithm is written by the author of libsodium and can be found [here](https://github.com/jedisct1/libsodium-xchacha20-siv).
Using one key for an entire column means that whoever can decrypt one row can decrypt them all from a database dump. Also changing (rotating) the key means rewriting the whole table.
@@ -153,11 +153,11 @@ Notice also how there is a `DEFAULT` value for the `key_id`. In a way, this give
### One Key ID per Row with Nonce Support
-The default cryptographic algorithm for the above approach uses a *nonceless* encryption algorithm called `[crypto_aead_det_xchacha20()](https://github.com/jedisct1/libsodium-xchacha20-siv)`. This algorithm has the advantage that it does not require nonce values, the disadvantage is that duplicate plaintexts will produce duplicate ciphertexts.
+The default cryptographic algorithm for the above approach uses a _nonceless_ encryption algorithm called `[crypto_aead_det_xchacha20()](https://github.com/jedisct1/libsodium-xchacha20-siv)`. This algorithm has the advantage that it does not require nonce values, the disadvantage is that duplicate plaintexts will produce duplicate ciphertexts.
-Nonces are some extra cryptographic context that is used in many cryptographic algorithms to produce different ciphertexts, even if the plaintexts are the same. The nonce does not have to be secret, but it *does* have to be unique. **pgsodium** comes with a useful function `pgsodium.crypto_aead_det_noncegen()` that will generate a cryptographically secure nonce for you, and in almost all cases it's best to use that function unless you know specifically what you are doing. In password hashing approaches, this is often similar to how a “salt” value is used to deduplicate password hashes.
+Nonces are some extra cryptographic context that is used in many cryptographic algorithms to produce different ciphertexts, even if the plaintexts are the same. The nonce does not have to be secret, but it _does_ have to be unique. **pgsodium** comes with a useful function `pgsodium.crypto_aead_det_noncegen()` that will generate a cryptographically secure nonce for you, and in almost all cases it's best to use that function unless you know specifically what you are doing. In password hashing approaches, this is often similar to how a “salt” value is used to deduplicate password hashes.
-Duplicate ciphertexts cannot be used to “attack the key”, it can only reveal the duplication. However, duplication is still information. In our examples so far, an attacker might be able to use this information to determine that two accounts share the same credit card number. While not technically breaking the encryption, this still leaks information to an attacker.
+Duplicate ciphertexts cannot be used to “attack the key”, it can only reveal the duplication. However, duplication is still information. In our examples so far, an attacker might be able to use this information to determine that two accounts share the same credit card number. While not technically breaking the encryption, this still leaks information to an attacker.
```sql
CREATE TABLE credit_cards (
@@ -172,15 +172,15 @@ SECURITY LABEL FOR pgsodium
IS 'ENCRYPT WITH KEY COLUMN key_id NONCE nonce';
```
-This is the most secure form of TCE - there is a unique key ID and a unique nonce per row.
+This is the most secure form of TCE - there is a unique key ID and a unique nonce per row.
### One Key ID per Row with Associated Data
-The encryption that is used for TCE is one of a family of functions provided by **libsodium** to do Authenticated Encryption with Associated Data or [AEAD Encryption](https://en.wikipedia.org/wiki/Authenticated_encryption). The “associated” data is plaintext (unencrypted) information that is mixed into the authentication signature of the encrypted data, such that when you authenticate the data, you also know that the associated data is authentic.
+The encryption that is used for TCE is one of a family of functions provided by **libsodium** to do Authenticated Encryption with Associated Data or [AEAD Encryption](https://en.wikipedia.org/wiki/Authenticated_encryption). The “associated” data is plaintext (unencrypted) information that is mixed into the authentication signature of the encrypted data, such that when you authenticate the data, you also know that the associated data is authentic.
-AEAD is helpful because often you have metadata associated with a secret, which isn't confidential but must not be forged.
+AEAD is helpful because often you have metadata associated with a secret, which isn't confidential but must not be forged.
-In our credit card example, we might associate a "`credit_card_number`" with an "`account_id`". But what if a malicious actor wanted to use someone else's credit card on their own account? If someone could forge the `account_id` data column, swapping an `account_id` with their own `account_id`, then you could be tricked into using the wrong credit card. By “associating” the `account_id` with the `credit_card_number`, it cannot be forged without throwing an error.
+In our credit card example, we might associate a "`credit_card_number`" with an "`account_id`". But what if a malicious actor wanted to use someone else's credit card on their own account? If someone could forge the `account_id` data column, swapping an `account_id` with their own `account_id`, then you could be tricked into using the wrong credit card. By “associating” the `account_id` with the `credit_card_number`, it cannot be forged without throwing an error.
Like above, this is done simply by extending the security label with the associated data column:
@@ -202,18 +202,18 @@ The new label indicates which column is to be associated with the secret, and th
## Using an Encrypted Table
-Now that you have TCE setup for a table, it's easy to use by simply inserting data into the table, and querying that data by looking at its generated view. The view is named `decrypted_` and by default is in the same schema as your table:
+Now that you have TCE setup for a table, it's easy to use by simply inserting data into the table, and querying that data by looking at its generated view. The view is named `decrypted_` and by default is in the same schema as your table:
```sql
INSERT INTO credit_cards (
credit_card_number,
account_id
-)
+)
VALUES
('1234-5678-8765-4321', 123);
```
-Now that you have inserted data, look at the table and notice how the credit card number is encrypted. This is the data that is stored on disk, the encrypted card number, the key id, and the account id, ********************************but the key itself is not stored********************************. This means if someone gets a backup or dump of your database, they cannot decrypt the credit card number, they do not have the key, only the key ID:
+Now that you have inserted data, look at the table and notice how the credit card number is encrypted. This is the data that is stored on disk, the encrypted card number, the key id, and the account id, **but the key itself is not stored**. This means if someone gets a backup or dump of your database, they cannot decrypt the credit card number, they do not have the key, only the key ID:
```sql
> select * from credit_cards where account_id = 123;
@@ -238,11 +238,11 @@ key_id | 7f753c4f-8c68-457a-8801-1798b2e9f44d
nonce | \x300a14aa721184ff7cf0f6bf088da267
```
-Notice how there is a new column called `decrypted_credit_card_number`. This column is not stored in database or on disk at all, it is generated “on-the-fly” as you select from the view. Database dumps do not contain this information, only the view itself, and most importantly, *************************************raw decryption keys are never stored*************************************.
+Notice how there is a new column called `decrypted_credit_card_number`. This column is not stored in database or on disk at all, it is generated “on-the-fly” as you select from the view. Database dumps do not contain this information, only the view itself, and most importantly, **raw decryption keys are never stored**.
## Future possibilities
-We're always thinking about the future possibilities for features and tools that we can bring to the PostgreSQL community, and we'd love to hear from you about what kind of encryption features you'd like to see. Some things we've considered but not yet explored yet are:
+We're always thinking about the future possibilities for features and tools that we can bring to the PostgreSQL community, and we'd love to hear from you about what kind of encryption features you'd like to see. Some things we've considered but not yet explored yet are:
- Built-in Key Management Server (KMS) with REST API ala AWS or GCP.
- Seamless Integration with external KMS services for key management.
@@ -251,7 +251,7 @@ We're always thinking about the future possibilities for features and tools that
- Group encryption using [signcryption](https://github.com/jedisct1/libsodium-signcryption)
- Your idea here?
-There's a lot of potential in the world of cryptography with Postgres and pgsodium, and we'd love to hear any ideas you may have as well. Join us in our [Discord #encryption channel](https://discord.com/channels/839993398554656828/1009906326480101417) if you want to chat more about it with us!
+There's a lot of potential in the world of cryptography with Postgres and pgsodium, and we'd love to hear any ideas you may have as well. Join us in our [Discord #encryption channel](https://discord.com/channels/839993398554656828/1009906326480101417) if you want to chat more about it with us!
## More Postgres Resources
diff --git a/apps/www/data/Developers.json b/apps/www/data/Developers.json
index da5baac96f6..a29460f0c5b 100644
--- a/apps/www/data/Developers.json
+++ b/apps/www/data/Developers.json
@@ -20,7 +20,7 @@
{
"text": "Careers",
"description": "Join the Supabase team and get involved.",
- "url": "https://about.supabase.com/careers",
+ "url": "https://supabase.com/careers",
"icon": "M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
}
]
diff --git a/apps/www/data/Pricing.json b/apps/www/data/Pricing.json
index 33a37a692bd..0fb1bc779ef 100644
--- a/apps/www/data/Pricing.json
+++ b/apps/www/data/Pricing.json
@@ -229,7 +229,7 @@
"icon": "M15.042 21.672L13.684 16.6m0 0l-2.51 2.225.569-9.47 5.227 7.917-3.286-.672zM12 2.25V4.5m5.834.166l-1.591 1.591M20.25 10.5H18M7.757 14.743l-1.59 1.59M6 10.5H3.75m4.007-4.243l-1.59-1.59",
"features": [
{
- "title": "Change Data Capture (CDC)",
+ "title": "Postgres Changes",
"tiers": {
"free": true,
"pro": true,
diff --git a/apps/www/data/career.json b/apps/www/data/career.json
index 348acdee2c3..d953fb5eaa1 100644
--- a/apps/www/data/career.json
+++ b/apps/www/data/career.json
@@ -30,7 +30,7 @@
{
"icon": "curious",
"title": "Polyglot",
- "text": "Broad skillets. Growth mindset."
+ "text": "Broad skillsets. Growth mindset."
},
{
"icon": "process",
diff --git a/apps/www/lib/redirects.js b/apps/www/lib/redirects.js
index ef43ecd11af..11d28e34e7c 100644
--- a/apps/www/lib/redirects.js
+++ b/apps/www/lib/redirects.js
@@ -1320,8 +1320,8 @@ module.exports = [
},
{
permanent: true,
- source: '/docs/guides/realtime/postgres-changes',
- destination: '/docs/guides/realtime/postgres-cdc',
+ source: '/docs/guides/realtime/postgres-cdc',
+ destination: '/docs/guides/realtime/postgres-changes',
},
{
permanent: true,
@@ -1565,4 +1565,9 @@ module.exports = [
source: '/docs/guides/functions/examples',
destination: '/docs/guides/functions',
},
+ {
+ permanent: true,
+ source: '/projects',
+ destination: 'https://app.supabase.com/projects',
+ },
]
diff --git a/apps/www/pages/company.tsx b/apps/www/pages/company.tsx
index 04a4b9537d0..bb2775767c8 100644
--- a/apps/www/pages/company.tsx
+++ b/apps/www/pages/company.tsx
@@ -103,7 +103,7 @@ const Team = () => {
- {enablePermissions
- ? "You need additional permissions to manage this organization's payment methods"
- : 'Only organization owners can update payment methods'}
+ You need additional permissions to manage this organization's payment methods
- {enablePermissions
- ? 'Contact your organization owner or adminstrator to create a new project.'
- : 'Only the organization owner can create new projects. Contact your organization owner to create a new project for this organization.'}
+ Contact your organization owner or adminstrator to create a new project.