Skip to content

Add spacetime lock/unlock to prevent accidental database deletion#4502

Open
clockwork-labs-bot wants to merge 2 commits intomasterfrom
bot/database-lock
Open

Add spacetime lock/unlock to prevent accidental database deletion#4502
clockwork-labs-bot wants to merge 2 commits intomasterfrom
bot/database-lock

Conversation

@clockwork-labs-bot
Copy link
Collaborator

Motivation

Feature request: "Is there any way we can lock a module to prevent it from being deleted? A bit concerned about some fat finger risk of accidentally deleting prod."

Solution

Adds a database lock mechanism. A locked database cannot be deleted until explicitly unlocked.

New CLI Commands

# Lock a database to prevent deletion
spacetime lock my-database

# Attempt to delete a locked database (fails with 403)
spacetime delete my-database
# Error: Database is locked and cannot be deleted. Run \`spacetime unlock\` first.

# Unlock when you actually need to delete
spacetime unlock my-database
spacetime delete my-database

Both commands support --server and --no-config flags, and resolve the database from spacetime.json when no argument is given (same as spacetime delete).

New HTTP API

  • POST /v1/database/:name_or_identity/lock -- Lock a database
  • POST /v1/database/:name_or_identity/unlock -- Unlock a database

Both require the same authorization as DELETE (owner only).

Implementation

  • Lock state stored in a separate database_locks sled tree in the standalone control DB (avoids changing the Database struct and needing a data migration)
  • ControlStateReadAccess::is_database_locked() and ControlStateWriteAccess::set_database_lock() added to the trait
  • delete_database route checks lock state before proceeding; returns 403 Forbidden with a descriptive message if locked
  • Locking is idempotent (locking an already-locked database is a no-op, same for unlock)
  • Lock only prevents deletion, not publishing updates

What is NOT locked

  • spacetime publish (updating module code) still works on locked databases
  • Only spacetime delete is blocked

This matches the intent: protect prod from accidental destruction while allowing normal deployments.

Adds a database lock mechanism to protect production databases from
accidental deletion via `spacetime delete`.

## Changes

### Server (client-api + standalone)
- Add `is_database_locked` to `ControlStateReadAccess` trait
- Add `set_database_lock` to `ControlStateWriteAccess` trait
- Implement both in standalone control DB using a `database_locks`
  sled tree (separate from the Database struct to avoid migration)
- Add `POST /v1/database/:name_or_identity/lock` route
- Add `POST /v1/database/:name_or_identity/unlock` route
- Check lock state in `delete_database` route handler; return 403
  with descriptive error if locked

### CLI
- Add `spacetime lock [database]` subcommand
- Add `spacetime unlock [database]` subcommand
- Both support `--server` and `--no-config` flags
- Both resolve database from spacetime.json when no argument given

## Usage

```bash
# Lock a database
spacetime lock my-database

# Attempt to delete (fails with 403)
spacetime delete my-database
# Error: Database is locked and cannot be deleted.
#        Run \`spacetime unlock\` first.

# Unlock when you really want to delete
spacetime unlock my-database
spacetime delete my-database
```
Lock now also prevents the reset route (which publish --delete-data
delegates to). Returns 403 with a message telling the user to unlock.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant