عطني ابديت — Give Me Update: متابعة مواضيع وتحديثات الفريق بالذكاء الاصطناعي (DeepSeek)
  • JavaScript 82.4%
  • CSS 7.5%
  • Shell 4.7%
  • HTML 4.1%
  • Dockerfile 0.7%
  • Other 0.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
balnaimi 04e1e916cd
All checks were successful
build-and-release / docker (push) Successful in 3s
fix(ci): build with -f after the Dockerfile moved
The 3.7.0 reorganisation moved Dockerfile to deploy/docker/app.Dockerfile, but
CI still ran "docker build ... ." which looks for it at the root. Run 72 failed
on v3.7.0 because of this.

Also fix the offline bundler: it passed the new -f path but kept "docker/" as the
trailing build context, so building the SimpleAuth image failed with
path "docker/" not found. Found by building the bundle on a real Docker host.
2026-10-13 09:00:24 +03:00
.forgejo/workflows fix(ci): build with -f after the Dockerfile moved 2026-10-13 09:00:24 +03:00
certs refactor!: English-only sources, coded API errors, English AI prompts 2026-10-12 10:42:46 +03:00
deploy fix(ci): build with -f after the Dockerfile moved 2026-10-13 09:00:24 +03:00
docs refactor: organise the repository by purpose 2026-10-13 08:54:21 +03:00
lib fix: full audit pass (security, data safety, robustness, UI) 2026-10-12 11:52:13 +03:00
public fix: second audit pass (archive flag, 405/Allow, markdown, a11y, bidi) 2026-10-12 12:01:34 +03:00
test refactor: organise the repository by purpose 2026-10-13 08:54:21 +03:00
tools refactor: organise the repository by purpose 2026-10-13 08:54:21 +03:00
.dockerignore feat: initial release of Give Me Update (عطني ابديت) 2026-08-31 08:06:55 +03:00
.env.example fix: full audit pass (security, data safety, robustness, UI) 2026-10-12 11:52:13 +03:00
.gitignore fix(offline): SimpleAuth could not find its certificate in the docker bundle 2026-10-12 12:56:00 +03:00
CHANGELOG.md feat: set-endpoint CLI + document the AI address and folders 2026-10-12 12:08:23 +03:00
docker-compose.yml refactor: organise the repository by purpose 2026-10-13 08:54:21 +03:00
package.json fix(ci): build with -f after the Dockerfile moved 2026-10-13 09:00:24 +03:00
README.md refactor: organise the repository by purpose 2026-10-13 08:54:21 +03:00
server.js fix: second audit pass (archive flag, 405/Allow, markdown, a11y, bidi) 2026-10-12 12:01:34 +03:00

Give Me Update

An AI-powered platform for tracking team topics and updates.

You create a topic with a title only, and whoever works on it writes their update in any language or dialect and in any style, and the AI (DeepSeek) summarises each update in Modern Standard Arabic, then re-reads the whole topic to produce a topic summary and a full report with the progress percentage and the next step.

Features

  • Title-only topics: Create a topic quickly and add the details later from inside the topic.
  • Edit a topic: Change the title, the details and the topic owner at any time.
  • Free-form updates: Anyone writes their update in any language or dialect with no formatting constraints.
  • A summary for every update in Modern Standard Arabic (the update is saved immediately even if analysis fails, with a retry button).
  • Topic summary + full report: Both are re-analysed after every update, with the progress percentage and the next step.
  • Edit updates: Any update can be edited, and an edit re-analyses the whole topic.
  • Search, filter and sort: Search by title, details or owner; filter (All/Active/Paused/Done/Stale/My topics); and sort by update, creation, title or percentage.
  • "Stale" indicator: An active topic that has not received an update for 7 days shows an alert.
  • Topic owner: Assign an owner to each topic and use the "My topics" filter.
  • Export the report: Copy or download the topic summary and its report (Markdown).
  • Archive separate from trash: Archive a topic to hide it from the list, or delete it to the trash and then restore it or delete it permanently.
  • Backup: Download a copy of all your data and restore it (JSON).
  • Built-in settings: the AI endpoint and key, plus the SimpleAuth connection, all from inside the app.
  • Unified sign-in: identity comes from SimpleAuth (OIDC) with a secure server-side session and a sign-out button.
  • Arabic/English with RTL/LTR direction switching, dark and light themes, and a bundled Tajawal font.
  • No external dependencies at runtime.

Deploying to an isolated (offline) network

The app has zero runtime dependencies, so moving it to a machine with no internet needs only Node itself and (optionally) the SimpleAuth binary. A bundle script collects everything, verifies the checksums, and produces one tarball:

bash deploy/offline/bundle.sh                # on a machine with internet
# -> dist/give-me-update-offline-<version>-linux-x64.tar.gz

# on the isolated machine
tar xzf give-me-update-offline-*.tar.gz && cd give-me-update-offline-*
bash app/deploy/offline/install.sh

Change the AI endpoint without a browser (the database owns it after the first run):

cd app && node deploy/offline/set-endpoint.mjs http://10.0.0.5:8200/v1 MyModel --list --test

Full walkthrough — including how to carry your existing data across and what does not work offline (building the Docker images): docs/OFFLINE.md.

Requirements

  • Node.js 22.5 or newer (uses the built-in node:sqlite).

Running locally

cp .env.example .env   # (optional) initial settings
npm start

Then open http://localhost:4000 and go to Settings to set the AI key.

Sign-in is disabled unless you set SAUTH_URL — see Users and sign-in.

Running with Docker Compose

docker compose up -d

The image is pulled from the Forgejo registry: git.majlis7.net/debe/give-me-update:latest

The data lives in a volume named give-me-update-data.

Time zone: the docker-compose.yml file sets TZ=Asia/Riyadh and the image installs tzdata, because without that the container runs on UTC and every time appears 3 hours behind. Change the value if your time zone is different.

Backup

  • From inside the app: Settings → "Download a copy" (a JSON file with all topics and updates), and "Import a copy" to restore.
  • Restoring replaces all current data with the data from the file.
  • From outside the app: copy the volume:
docker run --rm -v give-me-update-data:/data -v "$PWD:/backup" alpine \
  tar czf /backup/give-me-update-$(date +%F).tar.gz -C /data .

Tests

npm test

They cover: the database and migrations, the AI layer, the HTTP server, the UI, security, full end-to-end scenarios for everything a user does, and feature tests (saving before analysis, the archive, backup, incremental loading).

CI runs the tests before building the Docker image, so a failing version is never published.

Releases and CI

  • Semantic Versioning via version in package.json and vX.Y.Z tags.
  • CI (Forgejo Actions): pushing to main runs the tests, then builds the image and pushes it to the registry.
  • Releases: pushing a v* tag creates a Release automatically with the CHANGELOG.md section.
# release a new version
# 1) update version in package.json
# 2) add a section to CHANGELOG.md
git add -A && git commit -m "release: X.Y.Z"
git tag vX.Y.Z
git push origin main --tags

Project structure

.
├── server.js                # The server (plain Node, no dependencies)
├── lib/
│   ├── db.js                # The database (node:sqlite) + sessions
│   ├── ai.js                # AI connection and analysis
│   ├── simpleauth.js        # OIDC client (PKCE + JWKS + RS256)
│   └── auth.js              # Session helpers and signed payloads
├── public/
│   ├── index.html
│   ├── styles.css           # Color system (role-based tokens) + Tajawal font
│   ├── app.js
│   ├── i18n.js              # Arabic/English translations
│   └── fonts/               # Tajawal font (woff2)
├── test/
│   ├── unit/                # One module in isolation
│   ├── integration/         # A running server over HTTP
│   └── migration/           # Upgrading an older database
├── deploy/
│   ├── docker/
│   │   ├── app.Dockerfile        # The application image
│   │   └── simpleauth.Dockerfile # SimpleAuth (checksum-verified binary)
│   └── offline/             # Building and installing without internet
│       ├── bundle.sh             # Build the transferable bundle
│       ├── install.sh            # Install it on the isolated machine
│       ├── compose.py            # Compose file without build contexts
│       └── set-endpoint.mjs      # Change the AI endpoint from the terminal
├── tools/                   # Publishing and releasing
│   ├── publish.sh                # Push the image to the registry
│   ├── release.sh                # Tag a release
│   └── release.mjs
├── certs/                   # Your own TLS certificates (untracked)
├── docker-compose.yml       # The app + SimpleAuth (stays at the root: compose
│                            #   resolves .env and ./certs against this folder)
├── .forgejo/workflows/      # CI pipeline
├── docs/                    # Guides
├── CHANGELOG.md
└── package.json

Users and sign-in — SimpleAuth

The app never manages passwords at all. All identity comes from SimpleAuth via OIDC with PKCE:

Browser ──► /auth/login ──► SimpleAuth (sign-in page / SSO)
                ▲                    │
                └── /auth/callback ◄──┘  (?code=...)
                        │
                        └─► token exchange + local RS256 verification (JWKS) ⟹ a session of our own
  • Local verification of the RS256 signature via node:crypto and JWKS keys — no network request per request, and no npm package.
  • The author name is pinned to the signed-in user: nobody can post under someone else's name.
  • Roles: Whoever holds the admin role (SAUTH_ADMIN_ROLE, default admin) can open settings, delete and restore. Everyone else only sees topics and updates.
  • Automatic renewal: The session is renewed silently, and if the account is disabled in the directory the session is ended immediately.
  • Sign-out goes through /sauth/logout so that the SSO session is cleared as well.
  • Leave SAUTH_URL empty to disable sign-in entirely (development mode only — do not do this on a shared network).

Setup in 5 steps

cp .env.example .env      # 1) fill in SAUTH_HOSTNAME, SAUTH_ADMIN_KEY and APP_URL
mkdir -p certs            # 2) put your certificate: certs/fullchain.pem and certs/privkey.pem
docker compose up -d --build
  1. Open https://<SAUTH_HOSTNAME>:<SAUTH_PORT>/sauth/admin with the admin key.
  2. Apps → create an app: app_id = give-me-update with redirect_uris = ["https://<APP_URL>/auth/callback"]. Then Roles → define admin and member, and assign admin to whoever you want.
  3. Create the users (or connect AD later) and sign in.

⚠️ Without setting SAUTH_REDIRECT_URIS, SimpleAuth rejects every sign-in attempt — and that is intentional.

Environment variables: SAUTH_* vs AUTH_*

Two prefixes appear in this project, and the difference matters:

Prefix Where you set it Who reads it
SAUTH_* your .env file docker compose — it interpolates these
AUTH_* inside the SimpleAuth container SimpleAuth itself

The compose file maps one to the other, for example SAUTH_DEPLOYMENT_NAME → AUTH_DEPLOYMENT_NAME.

You almost always edit SAUTH_* in .env. The AUTH_* names are what SimpleAuth documents upstream, so they show up in its own documentation and log output — if you see AUTH_SOMETHING mentioned there, look for the matching SAUTH_SOMETHING in .env.

Runtime settings (deployment_name, redirect_uris, cors_origins, default_roles, rate limiting, AD outage behaviour, auto-SSO) are seeded from the environment on the first run only. Afterwards the admin UI owns them and the env value is ignored.

Deployment name (SAUTH_DEPLOYMENT_NAME)

A small variable, but it matters for AD later:

Constraint 6 letters maximum, letters only (no digits or dashes)
Default sauth
Purpose Names the AD service account: svc-sauth-{name}

It only matters if you run more than one SimpleAuth instance on the same AD (to avoid collisions between account names and SPNs). With a single instance, leave it as sauth.

⚠️ Important: this is a "runtime" setting — it is read from .env on the first run only. After that the source of truth is the panel: Settings → General. Changing it in .env later has no effect.

Moving to Active Directory (later)

No change to the Give Me Update code is needed — the app sends the browser to SimpleAuth, and SimpleAuth takes care of the rest:

  1. Admin panel → LDAP Providers → AD Setup Script — enter the service account name and download the PowerShell script.
  2. Run it on any domain-joined machine: it creates the account, registers the SPNs and exports a configuration file (no ktpass and no manual keytab).
  3. Paste the configuration into the panel — SimpleAuth builds the keytab in memory and enables SSO immediately.
  4. For transparent SSO: enable SAUTH_AUTO_SSO=true, and make sure SAUTH_HOSTNAME is the same name users type, and that the clocks are in sync (SPNEGO allows only a 5-minute difference). On Windows: the AuthServerAllowlist policy in Chrome/Edge. On Firefox: network.negotiate-auth.trusted-uris=<SAUTH_HOSTNAME>.

After AD is connected: a user who is disabled, expired or deleted in AD is blocked automatically at the first renewal (within the access token lifetime), even if their Kerberos ticket is still valid.

Security

  • No passwords in this app: no storage, no hashing and no reset — identity comes from SimpleAuth.
  • Tokens are verified locally with the RS256 signature plus iss and aud checks — so a token from another app is not accepted.
  • A session of our own: a random HttpOnly cookie with a record in the database (revocable immediately).
  • The author name comes from the session — you cannot impersonate anyone else.
  • Roles: settings, permanent deletion and restore are for the admin only.
  • Idle sessions are cleaned up automatically at startup (older than 30 days).
  • The DeepSeek key is stored on the server and is never sent to the browser in full (it is shown masked).
  • There are no external dependencies at runtime.