Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/workflows/rc7-source-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: rc.7 source audit

on:
push:
branches: [fix/rc7-remove-legacy-ai]
paths: [.github/workflows/rc7-source-audit.yml]

permissions:
contents: read

jobs:
source-audit:
runs-on: ubuntu-latest
timeout-minutes: 10
env:
DOTNET_INSTALL_DIR: /tmp/rateldesk-rc7/sdk
NUGET_PACKAGES: /tmp/rateldesk-rc7/packages
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6
with:
global-json-file: global.json
- name: Restore public build inputs
run: |
dotnet restore Helpdesk.sln
tar -czf - -C /tmp/rateldesk-rc7 sdk packages | split -b 350M -d - "$RUNNER_TEMP/build-inputs.part"
git ls-files '*AGENTS.md' '*SKILL.md'
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: rc7-inputs-00
path: ${{ runner.temp }}/build-inputs.part00
compression-level: 0
retention-days: 1
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: rc7-inputs-01
path: ${{ runner.temp }}/build-inputs.part01
compression-level: 0
retention-days: 1
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: rc7-inputs-02
path: ${{ runner.temp }}/build-inputs.part02
compression-level: 0
retention-days: 1
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: rc7-inputs-03
path: ${{ runner.temp }}/build-inputs.part03
compression-level: 0
retention-days: 1
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<VersionPrefix Condition="'$(VersionPrefix)' == ''">0.1.0</VersionPrefix>
<VersionSuffix Condition="'$(VersionSuffix)' == ''">rc.6</VersionSuffix>
<VersionSuffix Condition="'$(VersionSuffix)' == ''">rc.7</VersionSuffix>

<Version Condition="'$(Version)' == '' and '$(VersionSuffix)' == ''">$(VersionPrefix)</Version>
<Version Condition="'$(Version)' == '' and '$(VersionSuffix)' != ''">$(VersionPrefix)-$(VersionSuffix)</Version>
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Use an exact SemVer tag in production, or preferably replace tags with the publi

## Bundled PostgreSQL

For a fresh installation with PostgreSQL and the required `vector` and `pg_trgm` extensions, add the bundled sidecar overlay. Choose a unique password outside source control:
For a fresh installation with PostgreSQL, add the bundled sidecar overlay. Choose a unique password outside source control:

```bash
RATELDESK_POSTGRES_PASSWORD='replace-with-a-secret' \
Expand All @@ -58,7 +58,7 @@ At `/setup`, select PostgreSQL and enter host `postgres`, port `5432`, database

## External PostgreSQL

For an externally managed PostgreSQL database, start the normal source or release stack and enter its connection details at `/setup`; the API must be able to reach the database network. The target must be empty for a new setup and have the required `vector` and `pg_trgm` extensions installed by the database operator.
For an externally managed PostgreSQL database, start the normal source or release stack and enter its connection details at `/setup`; the API must be able to reach the database network. The target must be empty for a new setup.

```bash
docker compose -f docker/docker-compose.yml up --build
Expand Down
2 changes: 1 addition & 1 deletion docker/docker-compose.e2e.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
postgres:
image: pgvector/pgvector:pg16
image: postgres:16
environment:
POSTGRES_DB: rateldesk
POSTGRES_USER: rateldesk
Expand Down
3 changes: 1 addition & 2 deletions docker/docker-compose.postgres.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
services:
postgres:
image: pgvector/pgvector:pg16
image: postgres:16
environment:
POSTGRES_DB: ${RATELDESK_POSTGRES_DATABASE:-rateldesk}
POSTGRES_USER: ${RATELDESK_POSTGRES_USERNAME:-rateldesk}
POSTGRES_PASSWORD: ${RATELDESK_POSTGRES_PASSWORD:?Set RATELDESK_POSTGRES_PASSWORD before starting PostgreSQL}
volumes:
- rateldesk-postgres-data:/var/lib/postgresql/data
- ./postgres/init-extensions.sql:/docker-entrypoint-initdb.d/10-rateldesk-extensions.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s
Expand Down
2 changes: 0 additions & 2 deletions docker/postgres/init-extensions.sql

This file was deleted.

10 changes: 5 additions & 5 deletions docs/SELF_HOSTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ docker compose -f docker/docker-compose.yml exec api \

For PostgreSQL, set `Bootstrap__Unattended__Provider=PostgreSql` and
`Bootstrap__Unattended__PostgreSqlConnectionString` instead. The same bounded
preflight accepts only an empty target with `vector` and `pg_trgm` available.
preflight accepts only an empty target with the required database connectivity and permissions.
Completion writes the normal durable marker and descriptor. A restricted API
host observes that descriptor, exits, and Compose restarts it into the normal
runtime; it does not retain the unattended password.
Expand All @@ -120,11 +120,11 @@ SQLite uses its own EF Core migration assembly; setup and every normal API start

## PostgreSQL

An existing PostgreSQL deployment continues to use `ConnectionStrings__HelpdeskDb`; select `Database__Provider=PostgreSql` explicitly for new deployment-managed PostgreSQL configuration. Preserve the database and shared data-protection keys before an upgrade. PostgreSQL uses the existing provider-specific migration chain and requires the extensions used by it, including `vector` and `pg_trgm`; do not point RatelDesk at an unrelated or non-empty database.
An existing PostgreSQL deployment continues to use `ConnectionStrings__HelpdeskDb`; select `Database__Provider=PostgreSql` explicitly for new deployment-managed PostgreSQL configuration. Preserve the database and shared data-protection keys before an upgrade. PostgreSQL uses the existing provider-specific migration chain and does not require non-standard extensions; do not point RatelDesk at an unrelated or non-empty database.

### Bundled PostgreSQL

For a fresh local or single-host deployment, combine the default stack with [docker/docker-compose.postgres.yml](../docker/docker-compose.postgres.yml). It runs the compatible `pgvector/pgvector:pg16` image, creates `vector` and `pg_trgm` only when its new PostgreSQL volume is initialized, and keeps database data in a separate named volume:
For a fresh local or single-host deployment, combine the default stack with [docker/docker-compose.postgres.yml](../docker/docker-compose.postgres.yml). It runs the standard `postgres:16` image and keeps database data in a separate named volume:

```bash
RATELDESK_POSTGRES_PASSWORD='replace-with-a-secret' \
Expand Down Expand Up @@ -160,9 +160,9 @@ unset RATELDESK_POSTGRES_CONNECTION_STRING RATELDESK_BOOTSTRAP_ADMIN_EMAIL RATEL
docker compose -f docker/docker-compose.release.yml up -d
```

For a new instance, the target must be empty. RatelDesk tests the connection with bounded timeouts before it creates schema. It identifies a historical RatelDesk schema separately from an unrelated non-empty database, but refuses setup for both so an existing installation cannot be modified by a first-run session. The setup principal must be able to apply the existing migrations but does not need superuser access. A database administrator must install the required `vector` and `pg_trgm` extensions in the target database before setup, and should enforce TLS, least-privilege credentials, and provider-managed backups. Deployment-managed `ConnectionStrings__HelpdeskDb` supports both fresh setup and established installations. Readiness is determined from installation evidence, not from the presence of a connection string.
For a new instance, the target must be empty. RatelDesk tests the connection with bounded timeouts before it creates schema. It identifies a historical RatelDesk schema separately from an unrelated non-empty database, but refuses setup for both so an existing installation cannot be modified by a first-run session. The setup principal must be able to apply the existing migrations but does not need superuser access. Use TLS, least-privilege credentials, and provider-managed backups. Deployment-managed `ConnectionStrings__HelpdeskDb` supports both fresh setup and established installations. Readiness is determined from installation evidence, not from the presence of a connection string.

Back up an external deployment as a complete recovery set: a consistent PostgreSQL backup (including required extensions and roles according to the database provider's procedure), the bootstrap state directory, the shared data-protection key ring, and attachments. Test restoring that set into an isolated target before relying on it. To upgrade, take and verify this backup, deploy one versioned image release, and let the API apply its existing migration chain. If the migration fails, stop the new image and restore the complete recovery set; never point the original initialized descriptor at a new empty database to recover it.
Back up an external deployment as a complete recovery set: a consistent PostgreSQL backup and roles according to the database provider's procedure, the bootstrap state directory, the shared data-protection key ring, and attachments. Test restoring that set into an isolated target before relying on it. To upgrade, take and verify this backup, deploy one versioned image release, and let the API apply its existing migration chain. If the migration fails, stop the new image and restore the complete recovery set; never point the original initialized descriptor at a new empty database to recover it.

## Reverse proxy and Traefik

Expand Down
2 changes: 1 addition & 1 deletion docs/rc4-phase0-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ owned by `Directory.Build.props`.
| Surface | Existing state | rc.4 direction |
| --- | --- | --- |
| API startup | Requires `HelpdeskDb` and PostgreSQL Hangfire before serving. | Split bootstrap from the selected application runtime and gate workers until ready. |
| Database | Npgsql/pgvector is the runtime default; SQLite package is present but query and migration assumptions remain. | Explicit provider selection, provider migrations, SQLite query compatibility, and declared semantic-search capability. |
| Database | Historical rc.4 inventory: provider migration assumptions required review. | Explicit provider selection, provider migrations, and SQLite query compatibility. |
| Authentication | API validates external JWTs; Web uses OIDC/cookie forwarding; legacy BCrypt/JWT login is Development-only. | API-owned ASP.NET Core Identity local accounts, with OIDC retained as an opt-in scheme. |
| Identity links | Customer links could fall back to email and provisioning accepted body-controlled identity fields. | Use only validated issuer/subject or provider ID and explicit links. |
| Roles | Free-text user role plus claim bundles; generic role CRUD. | Protected built-ins, custom roles, permissions, and scoped assignments. |
Expand Down
Loading
Loading