Mattermost and Gitea store usernames as lowercase but SilverDESK passes
the original case (e.g. "Merlin" instead of "merlin"), causing 404/400
errors on case-sensitive API lookups.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds response body to the warning log when Mattermost user lookup fails,
making it easier to diagnose token/permission issues from logs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New users are now added to the SilverLABS Mattermost team after account
creation. Gitea provisioning is skipped for Testers (only Developers get
repo access). Role is parsed from ticket description and threaded through
the entire approval/confirmation flow. Gitea API token is now configured.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace 100+ raw system timezones with curated list of 26 major zones
with browser auto-detection via Intl API. Remove email requirement since
applicants receive a @silverlabs.uk address — fallback to username@silverlabs.uk
when no personal email is provided.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ticket replies now include full onboarding info (webmail, IMAP/SMTP, Mattermost, Gitea, SilverDESK URLs) instead of raw provisioning status. Confirmation success page uses clickable service links with email client config details.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The typed HttpClient has X-API-Key set as a default header, which caused
SilverDESK's MultiAuth policy to route to ApiKey auth instead of Bearer/JWT.
This made tickets owned by the MCP system user instead of the applicant.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace random unrecoverable passwords with a confirmation-based flow:
admin approval generates a secure token and sends a ticket reply with a
confirmation link; the developer clicks the link, enters their SilverDESK
password, and all services (Mattermost, Mailcow, Gitea) are provisioned
with that password. Adds password sync endpoint for SilverDESK resets and
updates the post-signup success panel to redirect to SilverDESK login with
the username pre-populated.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix two bugs preventing developer applications from appearing in SilverDESK:
1. Application creation payload used wrong types - ticketId was parsed as
int (GetInt32) but SilverDESK expects a Guid string, and appliedRole
was cast to int but the DTO expects "Tester"/"Developer" strings.
2. Approval provisioning now updates the DeveloperApplication record in
SilverDESK after Mattermost/Mailcow provisioning, setting status to
Approved and the correct provisioning flags.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace free-text timezone input with a dropdown populated from system
timezones. Replace "Why SilverLabs?" motivation section with a
skills-focused "What You Bring" section that collects what candidates
can contribute to the team, with role-specific placeholders.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SilverDESK rate-limits /api/auth/check-username after ~2 requests with a
5-minute cooldown. The old 500ms debounce per keystroke quickly exhausted
this limit, breaking the form. Now checks only on field blur, validates
format client-side while typing, and caches results to skip redundant calls.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CheckUsernameAsync returned false (taken) on any API failure, making every
username appear taken when SilverDESK was unreachable. Now returns nullable
bool so errors show a warning instead of blocking submission.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After registering the user and creating the ticket, call the
SilverDESK developer-program API to create a proper application
record linking the user and ticket. This ensures applications
appear in the /developer-program/applications dashboard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users now pick a password and get a SilverDESK account immediately on
submit. The form includes debounced username availability checking,
password fields with validation, and a post-submit link to SilverDESK.
The approval flow no longer creates a SilverDESK user (already exists)
and only provisions Mattermost + Mailcow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The approval endpoint now always returns 200 when provisioning was
attempted, with success/failure details in the response body. This
allows the SilverDESK webhook step to proceed with remaining actions
(note, reply, status change) even when individual services fail.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add the Mailcow read/write API key so mailbox provisioning actually
authenticates. Also set password2 to match password as required by
the Mailcow API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The CreateUserDto expects `fullName` and `password` but the payload
was sending `name` (wrong property name) and omitting password
entirely, causing 400 BadRequest validation errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change approve endpoint from int to string ticketId to match SilverDESK
GUIDs. Remove body parameter requirement so the endpoint works as a
webhook target. Add DeveloperTicketParsingService to fetch and parse
applicant details from ticket descriptions. Remove redundant ticket
status update from ProvisioningService since SilverDESK action engine
now handles SetStatus/AddNote/AddReply steps.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace .gitlab-ci.yml with .gitea/workflows/deploy.yml for build and
deploy pipeline. Deploy target updated to 10.0.0.247.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add developer application page with form submission that creates tickets
in SilverDESK. Includes provisioning service scaffolding for Mattermost,
Mailcow, and Gitea account creation. Fixes API key header casing
(X-API-Key) and ticket payload to match SilverDESK's CreateTicketDto
contract.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Blazor Web App requires the ASP.NET runtime to function properly,
as it uses interactive server components. Changed from nginx serving
static files to running the full .NET application.
Changes:
- Updated Dockerfile to use aspnet:9.0 runtime image
- Removed nginx configuration (no longer needed)
- Disabled HTTPS redirection (running behind reverse proxy)
- Added publish/ folder to .gitignore
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major architectural upgrade from static HTML site to modern Blazor Web App:
- Migrated to .NET 9.0 Blazor Web App framework
- Converted home page with 4 gateway cards (Help Desk, App Store, Cloud, SDK)
- Added new SDK card linking to comprehensive SDK documentation
- Converted SDK documentation page to Blazor component
- Updated template download links to nuget.silverlabs.uk repository
- Implemented multi-stage Docker build with .NET SDK 9.0
- Created Blazor-optimized nginx configuration
- Preserved all original styling and animations
- Added .gitignore for Blazor build artifacts
Technical changes:
- New BlazorApp/ project structure with Components architecture
- MainLayout simplified (no default navigation)
- CSS ported to wwwroot (styles.css + sdk-styles.css)
- Multi-stage Dockerfile: Build with dotnet SDK, serve with nginx
- GitLab CI/CD pipeline compatible (auto-detects new Dockerfile)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated both templates to always fetch the latest package versions:
- SilverSHELL packages now use Version="*"
- Microsoft .NET 9 packages use Version="9.*"
This ensures users always get the latest features and fixes without
needing to manually update template versions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated starter template package with fixed .csproj file that wraps
template preprocessor directives in XML comments for MSBuild/Rider
compatibility.
This resolves the error: "The element #text> beneath element is unrecognized"
Users can now open and work with the template in IDEs without errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed script.js include that was causing errors (no loading screen
on SDK page) and added 'visible' class directly to main-content div
so content displays immediately without JavaScript dependency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed cache expiry from 1 year to 1 hour and removed immutable flag
to allow browser cache updates. The 1-year cache was preventing logo
updates from being visible without clearing browser cache.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed the deployment script to properly expand variables in the SSH
session by removing single quotes from the heredoc delimiter. Also
added error handling with 'set -e' and removed dependency on
/opt/silverlabs/website directory that doesn't exist.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated the SilverLabs logo to use a transparent background for better
visual appearance against the gradient background. Removed the old logo.jpg
file and updated the Dockerfile to reflect this change.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The SDK directory was not being copied to the Docker image, causing
404 errors when accessing /sdk. Added COPY statement to include the
entire sdk/ directory with its subdirectories and downloadable templates.
Also added logo.jpg to the copy list for completeness.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated try_files directive to check for index.html in subdirectories
before falling back to root index.html. This fixes /sdk routing.
Before: try_files $uri $uri/ /index.html;
After: try_files $uri $uri/index.html /index.html;
Now /sdk correctly serves /sdk/index.html instead of root index.html
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added CI/CD pipeline with:
- Build stage: Creates Docker image from website files
- Deploy stage: Deploys to production server (PORTAINER-01)
- Automatic deployment on master/main branch
- Container runs on port 8100 mapped to internal port 80
- Available at https://silverlabs.uk
Pipeline deploys to:
- Server: 10.0.0.51 (PORTAINER-01)
- Port: 8100
- Docker container: silverlabs-website
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>