feat(banners): instance announcements — admin CRUD, top bar, CLI (#39)

banners table (title/body/level/active/dismissible/schedule window).
GET /banners/active for signed-in users; admin CRUD under /admin/banners.
BannerBar renders above the header with per-banner dismissal
(localStorage); admin console gains an Announcements section;
`containr banners` manages them and `auth status` prints active ones.

Generated with [Devin](https://devin.ai)

Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomáš DvořákandDevin authored and GitHub committed 2026-10-09 10:10:18 +02:00
1 parent 954a1d1f80
commit 9408464f12
21 files changed
+1301 -3

No files matched your search

+121
View File
@@ -2581,6 +2581,127 @@ paths:
items:
type: object
/banners/active:
get:
tags:
- Banners
summary: Active announcement banners
description: Banners currently active (enabled and within their optional schedule window).
security:
- bearerAuth: []
responses:
'200':
description: Active banners
content:
application/json:
schema:
type: object
properties:
banners:
type: array
items:
type: object
properties:
id: {type: string}
title: {type: string}
body: {type: string}
level: {type: string, enum: [info, success, warning, error]}
active: {type: boolean}
dismissible: {type: boolean}
starts_at: {type: string, format: date-time, nullable: true}
ends_at: {type: string, format: date-time, nullable: true}
created_at: {type: string, format: date-time}
/admin/banners:
get:
tags:
- Banners
summary: List all banners (admin)
security:
- bearerAuth: []
responses:
'200':
description: All banners
content:
application/json:
schema:
type: object
properties:
banners:
type: array
items:
type: object
post:
tags:
- Banners
summary: Create a banner (admin)
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [title]
properties:
title: {type: string}
body: {type: string}
level: {type: string, enum: [info, success, warning, error], default: info}
active: {type: boolean, default: true}
dismissible: {type: boolean, default: true}
starts_at: {type: string, format: date-time}
ends_at: {type: string, format: date-time}
responses:
'201':
description: Created banner
content:
application/json:
schema:
type: object
/admin/banners/{id}:
patch:
tags:
- Banners
summary: Update a banner (admin)
security:
- bearerAuth: []
parameters:
- {name: id, in: path, required: true, schema: {type: string}}
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
title: {type: string}
body: {type: string}
level: {type: string, enum: [info, success, warning, error]}
active: {type: boolean}
dismissible: {type: boolean}
starts_at: {type: string, format: date-time}
ends_at: {type: string, format: date-time}
responses:
'200':
description: Updated banner
content:
application/json:
schema:
type: object
delete:
tags:
- Banners
summary: Delete a banner (admin)
security:
- bearerAuth: []
parameters:
- {name: id, in: path, required: true, schema: {type: string}}
responses:
'204':
description: Deleted
# Audit Logs
/audit-logs:
get:
+2
View File
@@ -84,6 +84,8 @@ webhooks list|create|update|delete|deliveries|test
deliveries are HMAC-signed (X-Containr-Signature)
operations live ops view: active deploys, queue depth,
24h failures, cron runs, backups
banners list|create|update|delete announcement banners (admin);
active banners print on `auth status`
up deploy the current directory
```