feat: apikey alias/renewal + markdown/patch authorship

- APIKey.alias (unique, required). Creating with an existing alias
  renews that key: same key string kept, validity reset to 15d,
  reactivated, name/roles updated (response has renewed=true).
- get_actor(): X-API-Key -> key alias, Bearer -> 'admin'.
- markdown & patch create/update record author / created_at /
  updated_at / last_modified_by from the actor.
- Idempotent run_migrations() (information_schema-guarded ALTERs +
  backfill) so existing tables/data gain the new columns on startup;
  create_all still covers fresh DBs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
h z
2026-05-16 22:51:40 +01:00
parent 9e2477df8c
commit bf4c0dbbbd
8 changed files with 164 additions and 8 deletions

View File

@@ -9,7 +9,15 @@ class Markdown(Base):
id = Column(Integer, primary_key=True)
title = Column(String(255), nullable=False)
content = Column(Text, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.now(datetime.UTC))
created_at = Column(DateTime, default=lambda: datetime.datetime.now(datetime.UTC))
updated_at = Column(
DateTime,
default=lambda: datetime.datetime.now(datetime.UTC),
onupdate=lambda: datetime.datetime.now(datetime.UTC),
)
# Actor strings: alias of the API key, or 'admin' for KC-logged-in UI.
author = Column(String(255), nullable=True)
last_modified_by = Column(String(255), nullable=True)
path_id = Column(Integer, ForeignKey('path.id'), nullable=False)
order = Column(String(36), default=lambda: str(uuid.uuid4()))
shortcut = Column(String(36), default="")
@@ -21,6 +29,9 @@ class Markdown(Base):
'title': self.title,
'content': self.content,
'created_at': self.created_at,
'updated_at': self.updated_at,
'author': self.author,
'last_modified_by': self.last_modified_by,
'path_id': self.path_id,
'order': self.order,
'shortcut': self.shortcut,