feat: uuid ids everywhere, pickers for linked tickets, @pi/ui checkboxes

- Postgres: every table has a uuid `id` (gen_random_uuid()); the event
  store keeps its relay order in `seq`, and the lookup tables their
  uniqueness in constraints of their own.
- MongoDB: `_id` is Mongo's ObjectId; `id` is the domain id (the same
  uuid as the aggregate's stream in Postgres), unique, and every query
  goes by it. Production starts from empty databases.
- Web: linking tickets and hanging one from a parent are picked from a
  searchable select (links across projects, parents within the project)
  instead of typing a key; every checkbox is @pi/ui's pi-checkbox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 19:16:43 +02:00
parent 10c8f21ff4
commit 2c501a50d0
30 changed files with 292 additions and 207 deletions

View File

@@ -41,12 +41,14 @@ export class MongoAutomationsRepository extends AutomationsRepository {
}
async findById(id: string): Promise<Automation | null> {
const doc = await this.automations.findById(id).lean<AutomationDoc>();
const doc = await this.automations
.findOne({ id: id })
.lean<AutomationDoc>();
return doc ? (fromDoc(doc) as Automation) : null;
}
async insert({ id, ...rest }: Automation): Promise<void> {
await this.automations.create({ _id: id, ...rest });
await this.automations.create({ id, ...rest });
}
async update(
@@ -54,16 +56,16 @@ export class MongoAutomationsRepository extends AutomationsRepository {
changes: Partial<Pick<Automation, 'name' | 'active'>>,
): Promise<void> {
if (Object.keys(changes).length)
await this.automations.updateOne({ _id: id }, { $set: changes });
await this.automations.updateOne({ id }, { $set: changes });
}
async delete(id: string): Promise<void> {
await this.automations.deleteOne({ _id: id });
await this.automations.deleteOne({ id });
}
async claimRun(ruleId: string, eventKey: string): Promise<boolean> {
try {
await this.runs.create({ _id: `${ruleId}:${eventKey}`, at: new Date() });
await this.runs.create({ id: `${ruleId}:${eventKey}`, at: new Date() });
return true;
} catch (error) {
if ((error as { code?: number }).code === DUPLICATE_KEY) return false;
@@ -73,7 +75,7 @@ export class MongoAutomationsRepository extends AutomationsRepository {
async recordRun(id: string, error: string | null): Promise<void> {
await this.automations.updateOne(
{ _id: id },
{ id },
{
$inc: { runs: 1 },
$set: { lastRunAt: new Date().toISOString(), lastError: error },