#Changelog
This file is written for the installation owner: before upgrading, you read here what changed and whether anything needs your attention. It is not a development diary — the reasoning behind decisions and the technical detail live in docs/00-ilerleme.md.
The format is Keep a Changelog, the versions follow semantic versioning.
#What the version number tells you
x.y.z — semantic versioning.
- x increases: a backward-incompatible change. The name, place or behaviour of something in the interface or the API changed in a way that affects existing installations.
- y increases: a new capability, a new screen, a backward-compatible change in behaviour.
- z increases: bug fixes only.
What 1.0.0 promises, and what it does not. 1.0.0 says the interface and the API are now stable: from here on, a breaking change raises the major version. What it does not say is that the product is "finished" — the V2 scope (Git integration, dashboard reports, automation, a public API) is still ahead.
A version number is NOT a phase closing. The V1 exit criterion in docs/02-fonksiyonlar.md §6 — at least three teams outside Notussoft have started using the product regularly — is not met by 1.0.0. The two answer different questions: the version says "is the contract stable", the phase says "is the product in the field". That is why the phase table in CLAUDE.md still shows V1 as active, and it is not an inconsistency.
#The backward-compatibility promise
An upgrade never loses data. Dropping and renaming a column happens in two stages: first the new column is added and written to in parallel, and only a later release removes the old one. So as long as you do not skip a version, migrations are always forward-compatible.
Going back one version is supported, going back two is not: the migrations in between are not reversed. Taking a backup before upgrading is part of the procedure for exactly this reason (docs/self-hosted.md §3).
If a manual step is required it is written here as an "⚠ Upgrade note". If there is no such note, docker compose pull && docker compose up -d is enough.
#Unreleased
#Changed
- The second set of setting names is gone —
.envnow uses the names the application reads.NotusShip__Email__Hostinstead ofNOTUSSHIP_SMTP_HOST. The full list is indeploy/.env.example, anddocs/en/self-hosted.md§5 has a migration section.
The reason was a defect we hit ourselves. The thing translating the old names into the application's names was docker-compose.yml, so the translation only happened if compose was what started the container. On a platform that injects environment variables directly, the old names were set, visible inside the container, and never read — no error, no log line, the setting silently off. The translation table was not even identical across the three compose files.
> ⚠ Upgrade note. Rename the optional settings in your .env. Required > values and POSTGRES_* are unaffected, and so are NOTUSSHIP_MODE, > NOTUSSHIP_LICENSE, NOTUSSHIP_PROXY_COUNT, NOTUSSHIP_IMAGE, > NOTUSSHIP_PORT and NOTUSSHIP_BIND. > > A name you forget to change does not stay silent: at startup the > application lists every variable it can see but does not read, and names the > one to use instead. Values are never logged, only names. > > One trap while migrating: never leave a number or a true/false setting > empty. A blank NotusShip__Email__Port= is not the same as an unset one — > the application stops with Failed to convert configuration value ''. Write > the value or comment the line out. (The old compose hid this.)
- Every operator-facing message is now English. Server logs, CLI command output, start-up errors and health-check descriptions are fixed English instead of Turkish. The interface is unaffected — it stays bilingual and follows each user's preference.
The reason: someone searching an error message should find results, and the English documentation was telling operators to run commands whose output they could not read.
> ⚠ Upgrade note. If you have an alerting rule built on log lines (Uptime > Kuma, Grafana, a cron with grep), the patterns changed. The most common ones: > Veritabanı güncel, uygulanacak migration yok. → > Database is up to date, no migrations to apply., Yedekleme çalışmayacak: → > Backups will not run:, zorunlu yapılandırma eksik → > required configuration is missing.
api-token-issue --gunis now--days. The old name still works; you do not have to change your scripts. Only the new one appears in the usage line.
#Fixed
- The error banner shown when the application cannot start now follows your language. The banner exists before Blazor does, so it never reached the localizer and appeared in Turkish to English users — at the moment they needed help most.
- The page's
langattribute now reflects the chosen language. It was fixed attr, so screen readers pronounced an English interface in Turkish.
#1.0.0 — (21 August 2026)
The interface and the API were declared stable. The code side of the V1 scope is complete: multiple organizations, invitations and roles, password recovery, i18n (TR + EN), wiki, email notifications, global search, timesheet and time report, S3 storage, the iOS application and the self-hosted package.
This release is not a phase closing. The V1 exit criterion (docs/02-fonksiyonlar.md §6) is three teams outside Notussoft using it regularly; that has not been met. The only thing 1.0.0 says is that the interface and API contract will not break.
#Added
- Mobile application (iOS) — not distributed yet. Server address, sign-in, a four-tab shell; "assigned to me", inbox, issue detail (change status, assign, comment, stopwatch), a read-only board and quick issue creation. The session stays on the device. It requires no action from the installation owner today — there is no downloadable build and it asks for no server-side change. It is listed here because mobile will connect to the same server: self-hosted installations will need an externally reachable address and a valid TLS certificate.
- Wiki — a per-project page tree (reorder by drag and drop), markdown storage, an editor with a toolbar and preview, page templates (architecture decision record, meeting note, technical design).
- Wiki version history — every save is a version, with a line-by-line diff view and the ability to go back to a chosen version. Reverting does not erase history; it produces a new version.
- Issue references — writing
NSHIP-142in text turns it into a link; the title and status appear on hover. Works in wiki pages and issue descriptions. - Password recovery — "forgot my password" on the sign-in screen, a single-use link by email (valid for 1 hour), a new-password screen. Changing the password ends every session. On installations where email is not configured the screen says so plainly and points to the operator's
reset-passwordcommand. - Better search — issue, project and person search on a full-text backend (
tsvector+ GIN), tolerant of typos and insensitive to Turkish characters. Saved filters. - Email notifications — immediate or a daily digest, selectable per user and per organization.
- Multiple organizations — membership in more than one team with the same account, and switching between them.
- Timesheet and project time report — a weekly view, totals per person and per issue, CSV export.
- Interface language — Turkish and English; language and time zone are per-user preferences.
- Image preview for attachments — image attachments open in a window without being downloaded.
- Markdown in issue descriptions — headings, lists, tables, code blocks and quotes are rendered; editing uses the same editor as the wiki.
- The running version is visible — at the bottom of the side panel, at the
/api/versionendpoint, and for the operator in thedotnet NotusShip.Api.dll versioncommand. - Activity feed — recent changes per project and per organization: issues opened, fields changed and comments in one list. Reached from the side panel.
- Creating a new project — a + button on the PROJECTS heading in the side panel. Previously a project could only be created in the first-run wizard; there was no way at all to create a second one later.
- Completed sprints are visible — a collapsed section in the backlog: name, dates, completed points, the issue list and a velocity sparkline. Previously you could not see a closed sprint anywhere in the product; even the velocity figure was computed from data you could not look at.
- Inline editing in the backlog — status, assignee and priority can now be changed in the row; you do not have to open the issue detail.
- S3-compatible file storage (optional) — including MinIO, Cloudflare R2, Backblaze B2 and DigitalOcean Spaces. Local disk remains the default; to move to S3 it is enough to give the bucket name and the credentials. Because storage keys have the same shape on both providers, switching does not require touching the database — copy the files and fill in the settings (
deploy/.env.example).
#Changed
- Validation errors returned by the server now reach the user. Some forms swallowed the reason and showed a generic "could not be saved".
- The wiki editor is markdown, not rich text. TipTap was tried and could not be installed without a JS bundler; the measurements are in
docs/00-ilerleme.md. Since storage was already markdown, what you write is what is stored.
#Fixed
- The chosen theme was lost when the page was refreshed. The preference is now kept on your account (so it applies on another device too) and is applied while the page is loading — you no longer see the wrong theme for a moment on refresh.
- Organization logo — upload it from organization settings; it appears in the side panel next to the name. PNG, JPEG or WebP; up to 512 KB.
- An archived project can be brought back: organization settings now list archived projects with an "Unarchive" action. Archiving used to be a one-way door — an archived project could never be reached again.
- Issue detail now opens in place in "assigned to me" and the activity feed as well; neither takes you to the board any more.
- Issue detail opens in place in the backlog: clicking a row no longer takes you to the board, the panel opens beside the backlog, and closing it leaves you in the backlog.
- The backlog updates live: an issue your teammate pulled into a sprint or whose status they changed appears without a refresh.
- A concurrency conflict is no longer a 500: when two updates reach the same record in quick succession, you get a message that says what happened instead of "something went wrong".
- The description field in quick issue creation could not be typed into — the cursor jumped back to the title instantly and what you typed went into the title.
- An issue created in the backlog did not appear in the list; a refresh was needed, which made it possible to create the same issue twice.
- The close button of an issue panel opened from a URL did not work (when opened from the backlog, the activity feed or "assigned to me").
- The completed-sprint list was cut off at the first 10; all of them are shown now.
- The issue key in a backlog row did not look like a link; it was clickable but only revealed itself on hover.
- Screen readers: the six editable fields in the issue panel all had the exact same name ("Click to change"); the field name and its value are now read together.
- When English was selected the interface appeared in English for a moment and then reverted to Turkish.
- There was no way at all to reach the issue detail from a backlog row.
- Every return to the Write tab in the wiki editor produced an error banner, and the cursor did not go to the text.
- In quick issue creation, using "Add another" left the previous description on the screen while entering the second record.
#0.1.0 — V0 (18 August 2026)
The first working release. The scope is a software team running a sprint from start to finish:
- Organization, project and issue management; issue key (
NSHIP-142), type, priority, assignee, label, sub-task and issue links. - Kanban board — drag and drop, column definitions, filters.
- Sprint and backlog — starting and completing a sprint, story points, velocity.
- Time tracking — stopwatch and manual entry.
- In-app notifications and an inbox, live updates (SignalR).
- File attachments, comments and issue history.
- Invitation flow, three roles (Owner, Member, Viewer).
- License key — a signed key verified offline; an installation without a key runs on the free tier of 3 users.
- Self-hosted package — a single Docker image,
docker compose, automatic migrations at start-up, a nightly backup and a restore procedure.
⚠ Upgrade note (on the first upgrade to 0.1.0). Users have to hard-refresh once (Cmd/Ctrl + Shift + R). Older versions servedindex.htmlas cacheable and the copy left in the browser asks for file names that no longer exist. The server cannot fix this. It does not recur after this release.
#Cutting a release (for the maintainer)
- Raise
VersionPrefixinDirectory.Build.props. - In this file, replace the "Unreleased" heading with the version number and date, and open a new "Unreleased" section above it.
- Tag and build the image:
git tag v1.0.0 && git push --tags
docker build -f deploy/Dockerfile \
--build-arg NOTUSSHIP_COMMIT="$(git rev-parse --short HEAD)" \
-t ghcr.io/notussoft/notusship:v1.0.0 \
-t ghcr.io/notussoft/notusship:latest .
Without NOTUSSHIP_COMMIT the version carries only the semantic number. With it, the version command prints 1.0.0+abc1234 — which commit is running stops being a matter of debate.
The GHCR package is never made public (docs/dagitim.md).