Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
3d6b998
chore: bootstrap Rails 8.1 application skeleton
DanielDz21 Sep 3, 2026
77d008d
test: configure RSpec test suite and add Fase 0 boot smoke specs
DanielDz21 Sep 3, 2026
b6d8117
ci: run parallel RSpec suite alongside RuboCop, Brakeman and bundler-…
DanielDz21 Sep 3, 2026
9c4fcad
feat: add Rails 8 authentication scaffold with role-aware User model
DanielDz21 Sep 3, 2026
a83c247
feat: allow visitors to self-register as no_admin users
DanielDz21 Sep 3, 2026
63cb5bc
feat: redirect users to a role-based landing page after authentication
DanielDz21 Sep 3, 2026
25bb9e3
test: cover authentication, registration and role-based access
DanielDz21 Sep 3, 2026
c53c3da
feat: add Pundit authorization with UserPolicy
DanielDz21 Sep 3, 2026
6d71608
refactor: extract shared flash partial into the layout
DanielDz21 Sep 3, 2026
0432072
test: cover UserPolicy authorization matrix and forbidden-access redi…
DanielDz21 Sep 3, 2026
77a6a0b
feat: add Active Storage avatar attachment with content-type/size val…
DanielDz21 Sep 3, 2026
5ed74c8
feat: support setting an avatar via remote URL
DanielDz21 Sep 3, 2026
7706684
feat: add Admin::UsersController for full user CRUD and role toggling
DanielDz21 Sep 3, 2026
cf29977
feat: let users edit/delete their own profile and add a sign-out button
DanielDz21 Sep 3, 2026
c683a80
test: cover avatar validations, remote URL fetching and the download job
DanielDz21 Sep 3, 2026
53ecd18
test: cover admin user management and self-service profile CRUD
DanielDz21 Sep 3, 2026
7f42e57
feat: broadcast live dashboard counts over Solid Cable via Turbo Streams
DanielDz21 Sep 3, 2026
56566be
test: cover dashboard broadcast triggers and real-time updates across…
DanielDz21 Sep 3, 2026
0fbca4a
feat: parse CSV/XLSX spreadsheets into SpreadsheetImport records with…
DanielDz21 Sep 3, 2026
6b0c7a0
refactor: generalize the dashboard highlight Stimulus controller for …
DanielDz21 Sep 3, 2026
cce88ad
feat: process spreadsheet imports in the background with live progress
DanielDz21 Sep 3, 2026
50aa7d1
feat: add Admin::SpreadsheetImportsController with a live-updating pr…
DanielDz21 Sep 3, 2026
8b8f40f
test: cover spreadsheet import parsing, background processing and liv…
DanielDz21 Sep 3, 2026
ce35d8b
feat: add persistent role-aware navigation with a mobile menu toggle
DanielDz21 Sep 3, 2026
c6a43b4
refactor: extract shared Tailwind component classes and a form-errors…
DanielDz21 Sep 3, 2026
0d21230
feat: add real-time password confirmation matching and a minimum pass…
DanielDz21 Sep 3, 2026
211dabe
test: cover responsive navigation across two viewport sizes
DanielDz21 Sep 3, 2026
da83b1b
test: cover SQL injection, XSS escaping and CSRF protection
DanielDz21 Sep 3, 2026
e725f06
chore: replace deploy.yml scaffold placeholders with a real Kamal 2 c…
DanielDz21 Sep 3, 2026
b297df5
perf: enable Ruby 4's ZJIT in production and disable Rails' default YJIT
DanielDz21 Sep 3, 2026
8773426
feat: seed a bootstrap admin user
DanielDz21 Sep 3, 2026
25c2e61
docs: write final submission README with AI Usage Disclosure
DanielDz21 Sep 3, 2026
15c1cd6
i18n: translate flash messages and redirects to pt-BR
DanielDz21 Sep 3, 2026
bcd8ece
i18n: translate UI views and layouts to pt-BR
DanielDz21 Sep 3, 2026
bfe79a9
test: update system and request specs to match new pt-BR UI strings
DanielDz21 Sep 3, 2026
6729f0e
feat: implementa sidebar responsiva e layout admin corporativo
DanielDz21 Sep 3, 2026
30cfed3
refactor: moderniza visual das flash messages e componentes do CRUD
DanielDz21 Sep 3, 2026
5f8f714
config: adiciona traducoes i18n para pt-BR e padroniza coluna para nome
DanielDz21 Sep 3, 2026
8c791d8
feat: let admins mark a spreadsheet import as headerless
DanielDz21 Sep 3, 2026
869dfaa
test: cover the headerless spreadsheet import toggle
DanielDz21 Sep 3, 2026
4b2ad44
i18n: translate the password reset e-mail and confirmation tooltip to…
DanielDz21 Sep 3, 2026
19dba04
perf: preload associations to eliminate N+1 queries in admin index views
DanielDz21 Sep 3, 2026
7998fa1
perf: cache admin dashboard counts via Solid Cache
DanielDz21 Sep 3, 2026
9a2f13a
perf: skip redundant file revalidation on each import progress tick
DanielDz21 Sep 3, 2026
a36fe9b
feat: load admin user create/edit forms inline via Turbo Frames
DanielDz21 Sep 3, 2026
5d3c8d7
refactor: adopt more Rails 8 / Ruby 4 idioms
DanielDz21 Sep 3, 2026
b7ca9d4
test: close coverage gaps found during the optimization review
DanielDz21 Sep 3, 2026
8f6bdf3
docs: restore full project documentation in README.md
DanielDz21 Sep 4, 2026
1736efd
perf: throttle spreadsheet import broadcasts and decouple them from t…
DanielDz21 Sep 4, 2026
0bb4655
perf: append row errors instead of re-rendering the whole list each time
DanielDz21 Sep 4, 2026
2f83118
refactor: extract spreadsheet parsing and row-import logic into services
DanielDz21 Sep 4, 2026
64abf82
feat: e-mail imported users so they can set a real password
DanielDz21 Sep 4, 2026
1d93fb7
test: fix pending-migration rescue typo and enforce the coverage minimum
DanielDz21 Sep 4, 2026
23e9ded
chore: hardcode seeded credentials and add a seeded regular user
DanielDz21 Sep 4, 2026
4c55d7f
style: run Rustywind and Herb formatters over all ERB views
DanielDz21 Sep 4, 2026
d626090
fix: stop opening a browser tab per e-mail, log to console instead
DanielDz21 Sep 4, 2026
5a5400c
fix: stop the mobile header from covering the top of the page content
DanielDz21 Sep 4, 2026
ef7843d
ci: modernize the CodeQL workflow
DanielDz21 Sep 4, 2026
7e51688
ci: build Tailwind CSS before running the test suite
DanielDz21 Sep 4, 2026
bcb1b7e
ci: merge scan_ruby and scan_js into a single security_scan job
DanielDz21 Sep 4, 2026
fa3ff58
test: cover the forgot-password flow end-to-end
DanielDz21 Sep 4, 2026
16ded85
test: cover the profile-update validation-failure path and two avatar…
DanielDz21 Sep 4, 2026
af296cd
fix: add alt text to avatar images and remove the unused scaffold con…
DanielDz21 Sep 4, 2026
442e4d3
ci: cache Playwright browsers and restrict GITHUB_TOKEN permissions
DanielDz21 Sep 4, 2026
5168edc
ci: cache the Playwright npm package too, not just the browser binary
DanielDz21 Sep 4, 2026
2419808
docs: document ActiveStorage libvips dependency for Rails 7+
DanielDz21 Sep 4, 2026
c677be2
docs: document the Playwright browser install and pin the CLI version
DanielDz21 Sep 5, 2026
fe9e052
fix: boot the production image without a shared master key
DanielDz21 Sep 5, 2026
4de41a8
Merge pull request #1 from DanielDz21/developer/daniel-silva
DanielDz21 Sep 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files.

# Ignore git directory.
/.git/
/.gitignore

# Ignore bundler config.
/.bundle

# Ignore all environment files.
/.env*

# Ignore all default key files.
/config/master.key
/config/credentials/*.key

# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep

# Ignore pidfiles, but keep the directory.
/tmp/pids/*
!/tmp/pids/.keep

# Ignore storage (uploaded files in development and any SQLite databases).
/storage/*
!/storage/.keep
/tmp/storage/*
!/tmp/storage/.keep

# Ignore assets.
/node_modules/
/app/assets/builds/*
!/app/assets/builds/.keep
/public/assets

# Ignore CI service files.
/.github

# Ignore Kamal files.
/config/deploy*.yml
/.kamal

# Ignore development files
/.devcontainer

# Ignore Docker-related files
/.dockerignore
/Dockerfile*
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: bundler
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
124 changes: 124 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: CI

on:
pull_request:
push:
branches: [ master ]

permissions:
contents: read

jobs:
security_scan:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true

- name: Scan for common Rails security vulnerabilities using static analysis
run: bin/brakeman --no-pager

- name: Scan for known security vulnerabilities in gems used
run: bin/bundler-audit

- name: Scan for security vulnerabilities in JavaScript dependencies
run: bin/importmap audit

lint:
runs-on: ubuntu-latest
env:
RUBOCOP_CACHE_ROOT: tmp/rubocop
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true

- name: Prepare RuboCop cache
uses: actions/cache@v4
env:
DEPENDENCIES_HASH: ${{ hashFiles('.ruby-version', '**/.rubocop.yml', '**/.rubocop_todo.yml', 'Gemfile.lock') }}
with:
path: ${{ env.RUBOCOP_CACHE_ROOT }}
key: rubocop-${{ runner.os }}-${{ env.DEPENDENCIES_HASH }}-${{ github.ref_name == github.event.repository.default_branch && github.run_id || 'default' }}
restore-keys: |
rubocop-${{ runner.os }}-${{ env.DEPENDENCIES_HASH }}-

- name: Lint code for consistent style
run: bin/rubocop -f github

test:
runs-on: ubuntu-latest
env:
RAILS_ENV: test
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 22

- name: Determine the Playwright version to install (for Capybara system specs)
run: |
echo "PLAYWRIGHT_CLI_VERSION=$(bundle exec ruby -e 'require "playwright"; puts Playwright::COMPATIBLE_PLAYWRIGHT_VERSION.strip')" >> "$GITHUB_ENV"

- name: Cache the Playwright npm package
id: playwright-npm-cache
uses: actions/cache@v4
with:
path: node_modules
key: playwright-npm-${{ runner.os }}-${{ env.PLAYWRIGHT_CLI_VERSION }}

- name: Install the Playwright npm package
if: steps.playwright-npm-cache.outputs.cache-hit != 'true'
run: npm install playwright@${{ env.PLAYWRIGHT_CLI_VERSION }}

- name: Cache Playwright browser binaries
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ env.PLAYWRIGHT_CLI_VERSION }}

# Only the browser binary itself is cacheable — its OS-level dependencies are
# installed system-wide via apt and never persist on this ephemeral runner, but
# installing just those (no browser download) is fast, unlike --with-deps.
- name: Install Chromium and its OS dependencies (cache miss)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: ./node_modules/.bin/playwright install --with-deps chromium

- name: Install Chromium's OS dependencies only (cache hit)
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: ./node_modules/.bin/playwright install-deps chromium

- name: Build Tailwind CSS
run: bin/rails tailwindcss:build

- name: Prepare test databases in parallel
run: bin/rails parallel:create parallel:load_schema

- name: Run test suite in parallel
run: bundle exec parallel_rspec spec/

- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/

42 changes: 9 additions & 33 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,20 @@ on:

jobs:
CodeQL-Build:

runs-on: ubuntu-latest
permissions:
security-events: write
contents: read

steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
uses: actions/checkout@v4

# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}

# Initializes the CodeQL tools for scanning.
# Autodetects languages present in the repo (Ruby, JavaScript). No Autobuild
# step: that's only needed for compiled languages (C/C++, C#, Java), and this
# is a Ruby/Rails app with no compilation step.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl

# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language

#- run: |
# make bootstrap
# make release
uses: github/codeql-action/init@v3

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v3
61 changes: 61 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Bundler
/.bundle
/vendor/bundle

# Environment secrets
.env
.env.*
!.env.example
/config/master.key
/config/credentials/*.key

# SQLite databases
/storage/*.sqlite3
/storage/*.sqlite3-*

# Logs
/log/*
!/log/.keep

# Temp files
/tmp/*
!/tmp/.keep

# Uploaded files (local dev)
/storage/[^.]*/

# Assets build output
/public/assets
/public/packs

# Node (if ever needed)
/node_modules
yarn-error.log

# macOS
.DS_Store

# IDE
.idea/
.vscode/
*.swp
*.swo

# Coverage
/coverage

# Aider Chat
.aider*

# Ruby LSP
.ruby-lsp/

# RSpec persisted run status (--only-failures / --next-failure)
/spec/examples.txt

# Ignore key files for decrypting credentials and more.
/config/*.key


/app/assets/builds/*
!/app/assets/builds/.keep
3 changes: 3 additions & 0 deletions .kamal/hooks/docker-setup.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env sh

echo "Docker set up on $KAMAL_HOSTS..."
3 changes: 3 additions & 0 deletions .kamal/hooks/post-app-boot.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env sh

echo "Booted app version $KAMAL_VERSION on $KAMAL_HOSTS..."
14 changes: 14 additions & 0 deletions .kamal/hooks/post-deploy.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env sh

# A sample post-deploy hook
#
# These environment variables are available:
# KAMAL_RECORDED_AT
# KAMAL_PERFORMER
# KAMAL_VERSION
# KAMAL_HOSTS
# KAMAL_ROLES (if set)
# KAMAL_DESTINATION (if set)
# KAMAL_RUNTIME

echo "$KAMAL_PERFORMER deployed $KAMAL_VERSION to $KAMAL_DESTINATION in $KAMAL_RUNTIME seconds"
3 changes: 3 additions & 0 deletions .kamal/hooks/post-proxy-reboot.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env sh

echo "Rebooted kamal-proxy on $KAMAL_HOSTS"
3 changes: 3 additions & 0 deletions .kamal/hooks/pre-app-boot.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env sh

echo "Booting app version $KAMAL_VERSION on $KAMAL_HOSTS..."
51 changes: 51 additions & 0 deletions .kamal/hooks/pre-build.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env sh

# A sample pre-build hook
#
# Checks:
# 1. We have a clean checkout
# 2. A remote is configured
# 3. The branch has been pushed to the remote
# 4. The version we are deploying matches the remote
#
# These environment variables are available:
# KAMAL_RECORDED_AT
# KAMAL_PERFORMER
# KAMAL_VERSION
# KAMAL_HOSTS
# KAMAL_ROLES (if set)
# KAMAL_DESTINATION (if set)

if [ -n "$(git status --porcelain)" ]; then
echo "Git checkout is not clean, aborting..." >&2
git status --porcelain >&2
exit 1
fi

first_remote=$(git remote)

if [ -z "$first_remote" ]; then
echo "No git remote set, aborting..." >&2
exit 1
fi

current_branch=$(git branch --show-current)

if [ -z "$current_branch" ]; then
echo "Not on a git branch, aborting..." >&2
exit 1
fi

remote_head=$(git ls-remote $first_remote --tags $current_branch | cut -f1)

if [ -z "$remote_head" ]; then
echo "Branch not pushed to remote, aborting..." >&2
exit 1
fi

if [ "$KAMAL_VERSION" != "$remote_head" ]; then
echo "Version ($KAMAL_VERSION) does not match remote HEAD ($remote_head), aborting..." >&2
exit 1
fi

exit 0
Loading