Compare commits
4
Commits
d044277194
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58a087b118 | ||
|
|
8878326839 | ||
|
|
200a17e5bd | ||
|
|
4dd9f96a23 |
+19
-16
@@ -42,10 +42,10 @@ No item becomes `DONE` based only on compilation, an isolated happy path, screen
|
|||||||
| Branch | Sole or primary ownership |
|
| Branch | Sole or primary ownership |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `work/platform` | Maven/application baseline, feature-package foundation, Flyway migration files, account/security/bootstrap, internship lifecycle, integration credential lifecycle, notification delivery infrastructure, Docker, and CI. |
|
| `work/platform` | Maven/application baseline, feature-package foundation, Flyway migration files, account/security/bootstrap, internship lifecycle, integration credential lifecycle, notification delivery infrastructure, Docker, and CI. |
|
||||||
| `work/projects` | Projects, membership intervals, invitations, membership-exit requests, leadership terms, Project lifecycle, Project-scoped authorization, member-removal orchestration, and Project completion. |
|
| `work/projects` | Projects, membership intervals, invitations, membership-exit requests/readiness, leadership terms, Project lifecycle, Project-history authorization, transfer orchestration, and Project completion. |
|
||||||
| `work/tasks` | Tasks, generic creator/assignment actors, member self-Task rules, comments, work logs, fixed status transitions, assignment/reassignment, Task soft deletion, and Project Task-progress calculations. |
|
| `work/tasks` | Tasks, generic creator/assignment actors, pending-exit assignment exclusion, member self-Task rules, comments, work logs, fixed status transitions, batch reassignment/direct-removal transfer operations, Task soft deletion, and Project Task-progress/history queries. |
|
||||||
| `work/attendance` | Attendance-policy versions, configured workdays, global calendar, HolidayAPI import interpretation, attendance, corrections, leave, deadline schedulers, and attendance/compliance metrics. |
|
| `work/attendance` | Attendance-policy versions/history, configured workdays, global calendar/history, HolidayAPI import interpretation, attendance, corrections, leave, deadline schedulers, and attendance/compliance metrics. |
|
||||||
| `work/reports-ui` | Shared Thymeleaf shell/fragments, Tailwind tokens/assets, dashboards, invitation/exit-request screens, shared report datasets, Chart.js presentation, XLSX/PDF exports, and cross-product UI/accessibility consistency. |
|
| `work/reports-ui` | Shared Thymeleaf shell/fragments, Tailwind tokens/assets, dashboards, invitation/exit/transfer screens, Project and Admin-setting History tabs, shared report datasets, Chart.js presentation, XLSX/PDF exports, and cross-product UI/accessibility consistency. |
|
||||||
|
|
||||||
Conflict-prevention rules:
|
Conflict-prevention rules:
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ Conflict-prevention rules:
|
|||||||
- `work/platform` owns `src/main/resources/db/migration/**`, Maven/dependency configuration, Compose, container build files, and CI workflow files. Other branches request schema changes instead of independently allocating migration versions.
|
- `work/platform` owns `src/main/resources/db/migration/**`, Maven/dependency configuration, Compose, container build files, and CI workflow files. Other branches request schema changes instead of independently allocating migration versions.
|
||||||
- `work/reports-ui` owns shared templates/fragments, shared design tokens, and general UI assets. Each domain branch owns its module-specific controllers and pages while consuming those shared fragments.
|
- `work/reports-ui` owns shared templates/fragments, shared design tokens, and general UI assets. Each domain branch owns its module-specific controllers and pages while consuming those shared fragments.
|
||||||
- A targeted repair shall use a clean, isolated `work/fix/<feature>/<what-fix>` branch and worktree from the taskmaster-verified current `main`. Do not use `work/<feature>/fix/<what-fix>`: the persistent `work/<feature>` ref already occupies that Git ref prefix.
|
- A targeted repair shall use a clean, isolated `work/fix/<feature>/<what-fix>` branch and worktree from the taskmaster-verified current `main`. Do not use `work/<feature>/fix/<what-fix>`: the persistent `work/<feature>` ref already occupies that Git ref prefix.
|
||||||
- `work/tasks` exposes focused Task query/transfer operations required by Project workflows. `work/projects` owns the transaction that removes a member or completes a Project.
|
- `work/tasks` exposes focused Task eligibility, batch-transfer, unfinished-count, and retained-history operations required by Project workflows. `work/projects` owns pending-exit readiness/approval, direct-removal orchestration, and Project completion transactions.
|
||||||
- `work/platform` owns HolidayAPI credential storage and the tested HTTP client. `work/attendance` owns preview interpretation, selection, deduplication, import, and day-off effects.
|
- `work/platform` owns HolidayAPI credential storage and the tested HTTP client. `work/attendance` owns preview interpretation, selection, deduplication, import, and day-off effects.
|
||||||
- Attendance time and Task work time remain separate. No branch may make one mutate or prove the other.
|
- Attendance time and Task work time remain separate. No branch may make one mutate or prove the other.
|
||||||
- Do not introduce a generic workflow engine, generic event-sourcing layer, multi-assignee Task model, Project-level day-off model, or speculative cross-module abstraction.
|
- Do not introduce a generic workflow engine, generic event-sourcing layer, multi-assignee Task model, Project-level day-off model, or speculative cross-module abstraction.
|
||||||
@@ -167,9 +167,9 @@ Iteration 2 starts only after every continuing branch incorporates the integrate
|
|||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| I2-TSK-01 | Add dated 1–1440-minute Task work logs and author corrections. | Membership/date boundaries and author-only editing. | `TODO` | — | — |
|
| I2-TSK-01 | Add dated 1–1440-minute Task work logs and author corrections. | Membership/date boundaries and author-only editing. | `TODO` | — | — |
|
||||||
| I2-TSK-02 | Enforce the combined 1440-minute daily total across all Projects. | PostgreSQL integration and concurrent over-allocation proof. | `TODO` | — | — |
|
| I2-TSK-02 | Enforce the combined 1440-minute daily total across all Projects. | PostgreSQL integration and concurrent over-allocation proof. | `TODO` | — | — |
|
||||||
| I2-TSK-03 | Reassign unfinished Tasks while preserving creator, state, comments, and work history and updating generic assignment actor/time. | DONE requires assignee reopen; creator attribution and prior logs/comments remain unchanged. | `TODO` | — | — |
|
| I2-TSK-03 | Reassign unfinished Tasks while preserving creator, state, comments, work logs, lifecycle timestamps, and assignment actor/time; exclude pending exit targets from new/self-assignment. | DONE requires assignee reopen; prior attribution remains; pending target keeps existing assignee rights but receives no new work. | `TODO` | — | — |
|
||||||
| I2-TSK-04 | Implement Task edit/soft deletion and authorized historical inspection for Leader and self-Task creator. | Leader controls any unfinished Task; creator controls only while still current assignee; deleted Task leaves normal progress but remains historical. | `TODO` | — | — |
|
| I2-TSK-04 | Implement Task edit/soft deletion and authorized historical inspection for Leader/self-Task creator plus Project History projection. | Eligible creator controls only while current assignee; deleted/completed Tasks expose retained attribution without invented previous-assignee or edit/status timelines. | `TODO` | — | — |
|
||||||
| I2-TSK-05 | Provide Task transfer and completion-query operations to the Projects module. | Atomic bulk transfer behavior and non-deleted/DONE counts. | `TODO` | — | — |
|
| I2-TSK-05 | Provide repeatable multi-Task/one-recipient transfer batches, unfinished-count, direct-removal transfer, and completion-query operations to Projects. | Each batch is atomic; recipient/pending state rechecked; direct removal transfers all unfinished Tasks atomically; non-deleted/DONE counts remain correct. | `TODO` | — | — |
|
||||||
| I2-TSK-06 | Complete Project status counts, percentage, total minutes, and per-member work queries. | Empty `N/A`, authorization scopes, hand-checkable totals. | `TODO` | — | — |
|
| I2-TSK-06 | Complete Project status counts, percentage, total minutes, and per-member work queries. | Empty `N/A`, authorization scopes, hand-checkable totals. | `TODO` | — | — |
|
||||||
|
|
||||||
### 5.3 `work/projects`
|
### 5.3 `work/projects`
|
||||||
@@ -178,17 +178,17 @@ Iteration 2 starts only after every continuing branch incorporates the integrate
|
|||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| I2-PRJ-01 | Issue and revoke non-expiring Leader invitations while retaining the issuing leadership term. | Eligibility, one pending Project/Intern pair, Leader-own versus Mentor-any revocation, ordinary notification behavior. | `TODO` | — | — |
|
| I2-PRJ-01 | Issue and revoke non-expiring Leader invitations while retaining the issuing leadership term. | Eligibility, one pending Project/Intern pair, Leader-own versus Mentor-any revocation, ordinary notification behavior. | `TODO` | — | — |
|
||||||
| I2-PRJ-02 | Let only the intended authenticated Intern accept or decline; support Mentor direct-add supersession. | Email is not a bearer join token; exactly one membership; terminal status/code and provenance retained. | `TODO` | — | — |
|
| I2-PRJ-02 | Let only the intended authenticated Intern accept or decline; support Mentor direct-add supersession. | Email is not a bearer join token; exactly one membership; terminal status/code and provenance retained. | `TODO` | — | — |
|
||||||
| I2-PRJ-03 | Create/cancel Leader-removal and member-leave requests without changing current rights. | Nonblank reason, same-Project/type shape, one pending request per target, requester-only cancellation. | `TODO` | — | — |
|
| I2-PRJ-03 | Create/cancel Leader-removal and member-leave requests, expose persistent readiness warnings, and keep existing rights while excluding the target from new/self-assignment. | Nonblank reason, same-Project/type shape, one pending request per target, requester-only cancellation, replacement/remaining/ready state for every authorized viewer. | `TODO` | — | — |
|
||||||
| I2-PRJ-04 | Let only the owning Mentor approve/reject exits, using the assisted unfinished-Task transfer and Leader-replacement transaction. | Transfer/replacement/interval/request resolution commit together; reject/cancel changes request only. | `TODO` | — | — |
|
| I2-PRJ-04 | Let only the owning Mentor approve/reject exits after Leader-managed redistribution; preserve the direct-removal automatic-transfer shortcut. | Leader exit requires replacement first; repeated batches persist; cancel/reject keeps them and restores eligibility; approval waits for non-Leader/zero unfinished Tasks; closure/request resolution commit together. | `TODO` | — | — |
|
||||||
| I2-PRJ-05 | Retain leadership history, change Leader without moving assignments, and complete only when every non-deleted Task is `DONE`. | Exactly one current Leader in PLANNED/ACTIVE; completion closes intervals, revokes invitations, and supersedes exits. | `TODO` | — | — |
|
| I2-PRJ-05 | Retain leadership history, change Leader without moving assignments, and complete only when every non-deleted Task is `DONE`. | Exactly one current Leader in PLANNED/ACTIVE; completion closes intervals, revokes invitations, and supersedes exits. | `TODO` | — | — |
|
||||||
| I2-PRJ-06 | Provide invitation, exit, former-member, and completed-Project historical read-only views. | Historical visibility and attribution without stale mutation authority. | `TODO` | — | — |
|
| I2-PRJ-06 | Provide one authorized Project History view for membership, leadership, invitation, exit decision, completed/soft-deleted Task, comment, work-log, and retained attribution data. | Admin all read-only; owning Mentor/current member on open Project; removed member denied until completion; no fabricated previous-assignee/status/edit timeline. | `TODO` | — | — |
|
||||||
|
|
||||||
### 5.4 `work/attendance`
|
### 5.4 `work/attendance`
|
||||||
|
|
||||||
| ID | Deliverable | Test/evidence emphasis | Status | Owner/date | Result/commit |
|
| ID | Deliverable | Test/evidence emphasis | Status | Owner/date | Result/commit |
|
||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| I2-ATT-01 | Schedule future-month attendance-policy versions, including separate grace values, and preserve effective history. | First-of-future-month rule; effective immutability; old checkout cutoff/report stability. | `TODO` | — | — |
|
| I2-ATT-01 | Schedule future-month attendance-policy versions, including separate grace values, preserve effective history, and expose Admin-only Policy History. | First-of-future-month rule; effective immutability; old cutoff/report stability; safe version/actor/effective metadata only. | `TODO` | — | — |
|
||||||
| I2-ATT-02 | Preview/import VN HolidayAPI candidates with Admin selection, override, provenance, and deduplication. | Public suggestion not authority; manual fallback; repeated import safety. | `TODO` | — | — |
|
| I2-ATT-02 | Preview/import VN HolidayAPI candidates with Admin selection, override, provenance, deduplication, and Admin-only Calendar History. | Public suggestion not authority; manual fallback; repeated import safety; past/current event metadata remains read-only and non-secret. | `TODO` | — | — |
|
||||||
| I2-ATT-03 | Materialize frozen full-day leave allocations and monthly/cross-month quota reservations. | Workday/day-off classification, policy snapshot, quota per month. | `TODO` | — | — |
|
| I2-ATT-03 | Materialize frozen full-day leave allocations and monthly/cross-month quota reservations. | Workday/day-off classification, policy snapshot, quota per month. | `TODO` | — | — |
|
||||||
| I2-ATT-04 | Implement leave submit/approve/reject/cancel and overlap protection. | Same-day boundary, pending/approved reservations, concurrent overlap/quota. | `TODO` | — | — |
|
| I2-ATT-04 | Implement leave submit/approve/reject/cancel and overlap protection. | Same-day boundary, pending/approved reservations, concurrent overlap/quota. | `TODO` | — | — |
|
||||||
| I2-ATT-05 | Implement missed-checkout correction submission and effective-checkout derivation. | Reject before/at checkout cutoff; accept afterward through scheduled end +24 hours; raw checkout remains null. | `TODO` | — | — |
|
| I2-ATT-05 | Implement missed-checkout correction submission and effective-checkout derivation. | Reject before/at checkout cutoff; accept afterward through scheduled end +24 hours; raw checkout remains null. | `TODO` | — | — |
|
||||||
@@ -200,7 +200,7 @@ Iteration 2 starts only after every continuing branch incorporates the integrate
|
|||||||
| ID | Deliverable | Test/evidence emphasis | Status | Owner/date | Result/commit |
|
| ID | Deliverable | Test/evidence emphasis | Status | Owner/date | Result/commit |
|
||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| I2-UI-01 | Complete Admin/Mentor/Intern/Leader dashboards and notification UI. | Authorization-correct actions and deadline/state summaries. | `TODO` | — | — |
|
| I2-UI-01 | Complete Admin/Mentor/Intern/Leader dashboards and notification UI. | Authorization-correct actions and deadline/state summaries. | `TODO` | — | — |
|
||||||
| I2-UI-02 | Complete account, integration, Project, invitation, membership-exit, Task, policy/calendar, attendance, correction, and leave desktop workflows using shared fragments. | Leader invite/revoke/removal request, Intern accept/decline/leave/cancel, and Mentor exit decision forms retain safe input and expose conflicts clearly. | `TODO` | — | — |
|
| I2-UI-02 | Complete account, integration, Project, invitation, membership-exit/transfer, Task, policy/calendar, attendance, correction, leave, and History desktop workflows using shared fragments. | Persistent warning; Leader-only multi-Task/one-recipient drawer; Mentor readiness decision; Project History; Admin-only Policy/Calendar/SMTP/HolidayAPI History; keyboard operation, redaction, and clear conflicts. | `TODO` | — | — |
|
||||||
| I2-UI-03 | Build one authorized attendance/compliance HTML report dataset. | Date filters, detailed versus own scope, formulas and `N/A`. | `TODO` | — | — |
|
| I2-UI-03 | Build one authorized attendance/compliance HTML report dataset. | Date filters, detailed versus own scope, formulas and `N/A`. | `TODO` | — | — |
|
||||||
| I2-UI-04 | Build one authorized Project/Task HTML report dataset. | Project/member/status/date filters and per-member visibility rules. | `TODO` | — | — |
|
| I2-UI-04 | Build one authorized Project/Task HTML report dataset. | Project/member/status/date filters and per-member visibility rules. | `TODO` | — | — |
|
||||||
| I2-UI-05 | Add only meaningful Chart.js trends with adjacent text/table alternatives. | Accessible label, equivalent data, theme tokens, reduced motion. | `TODO` | — | — |
|
| I2-UI-05 | Add only meaningful Chart.js trends with adjacent text/table alternatives. | Accessible label, equivalent data, theme tokens, reduced motion. | `TODO` | — | — |
|
||||||
@@ -221,10 +221,13 @@ Exit demonstration:
|
|||||||
- Admin previews/imports holidays and overrides a suggested day-off decision.
|
- Admin previews/imports holidays and overrides a suggested day-off decision.
|
||||||
- Intern submits cross-month leave and Mentor decides it.
|
- Intern submits cross-month leave and Mentor decides it.
|
||||||
- Intern submits a missed-checkout correction; Mentor decides and may revert it inside the window.
|
- Intern submits a missed-checkout correction; Mentor decides and may revert it inside the window.
|
||||||
- Leader reassigns an unfinished Task while preserving work history.
|
- Leader reassigns an unfinished Task while preserving creator, comments, work logs, and current assignment attribution.
|
||||||
- Leader invites an eligible Intern; the signed-in Intern accepts or declines; Mentor direct-add safely supersedes a pending invite.
|
- Leader invites an eligible Intern; the signed-in Intern accepts or declines; Mentor direct-add safely supersedes a pending invite.
|
||||||
- Mentor changes Leader without moving the former Leader's Tasks.
|
- Mentor changes Leader without moving the former Leader's Tasks.
|
||||||
- Member requests to leave and Leader requests removal; Mentor rejects or approves through assisted transfer and required replacement.
|
- Member requests to leave and Leader requests removal; all authorized viewers see readiness, replacement is appointed first when needed, Leader redistributes unfinished Tasks in repeated batches, cancellation/rejection keeps completed batches, and approval waits for zero unfinished Tasks.
|
||||||
|
- Mentor directly removes an ordinary member and a Leader in separate cases; automatic transfer remains atomic and completed Tasks keep the removed Intern's displayed name.
|
||||||
|
- Admin, owning Mentor, current member, and removed member before/after completion receive the exact Project History visibility defined by AUTH-006.
|
||||||
|
- Admin opens read-only Attendance Policy, Calendar, SMTP, and HolidayAPI History tabs; non-Admins are denied and no secret/internal retry data appears.
|
||||||
- Mentor completes a Project after all non-deleted Tasks are done.
|
- Mentor completes a Project after all non-deleted Tasks are done.
|
||||||
- Ordinary domain actions retain in-app notifications when SMTP is unavailable.
|
- Ordinary domain actions retain in-app notifications when SMTP is unavailable.
|
||||||
- Full integrated tests pass at the iteration integration commit.
|
- Full integrated tests pass at the iteration integration commit.
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ concurrency:
|
|||||||
group: container-${{ gitea.workflow }}-${{ gitea.ref }}
|
group: container-${{ gitea.workflow }}-${{ gitea.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: git.sechmachine.io.vn
|
||||||
|
IMAGE_NAME: sechmachine/labtimesheet
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
verify:
|
verify:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -66,6 +70,9 @@ jobs:
|
|||||||
needs: verify
|
needs: verify
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
steps:
|
steps:
|
||||||
- name: Check out source
|
- name: Check out source
|
||||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
@@ -78,22 +85,18 @@ jobs:
|
|||||||
- name: Select image tags
|
- name: Select image tags
|
||||||
id: image
|
id: image
|
||||||
env:
|
env:
|
||||||
CONFIGURED_IMAGE: ${{ vars.CONTAINER_IMAGE }}
|
|
||||||
EVENT_NAME: ${{ gitea.event_name }}
|
EVENT_NAME: ${{ gitea.event_name }}
|
||||||
GITEA_REF: ${{ gitea.ref }}
|
GITEA_REF: ${{ gitea.ref }}
|
||||||
GITEA_SHA: ${{ gitea.sha }}
|
GITEA_SHA: ${{ gitea.sha }}
|
||||||
run: |
|
run: |
|
||||||
publish=false
|
publish=false
|
||||||
image=labtimesheet
|
image="$REGISTRY/$IMAGE_NAME"
|
||||||
if [ "$EVENT_NAME" = "push" ] && [ "$GITEA_REF" = "refs/heads/main" ]; then
|
if [ "$EVENT_NAME" = "push" ] && [ "$GITEA_REF" = "refs/heads/main" ]; then
|
||||||
test -n "$CONFIGURED_IMAGE" || { echo "Repository variable CONTAINER_IMAGE is required" >&2; exit 1; }
|
|
||||||
publish=true
|
publish=true
|
||||||
image="$CONFIGURED_IMAGE"
|
|
||||||
fi
|
fi
|
||||||
{
|
{
|
||||||
echo "publish=$publish"
|
echo "publish=$publish"
|
||||||
echo "image=$image"
|
echo "image=$image"
|
||||||
echo "registry=${image%%/*}"
|
|
||||||
echo "tags<<EOF"
|
echo "tags<<EOF"
|
||||||
echo "$image:sha-${GITEA_SHA}-amd64"
|
echo "$image:sha-${GITEA_SHA}-amd64"
|
||||||
if [ "$publish" = "true" ]; then
|
if [ "$publish" = "true" ]; then
|
||||||
@@ -107,8 +110,8 @@ jobs:
|
|||||||
if: steps.image.outputs.publish == 'true'
|
if: steps.image.outputs.publish == 'true'
|
||||||
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||||
with:
|
with:
|
||||||
registry: ${{ steps.image.outputs.registry }}
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
username: ${{ gitea.actor }}
|
||||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
- name: Build AMD64 image and publish main
|
- name: Build AMD64 image and publish main
|
||||||
@@ -128,6 +131,9 @@ jobs:
|
|||||||
needs: verify
|
needs: verify
|
||||||
runs-on: ubuntu-latest-arm
|
runs-on: ubuntu-latest-arm
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
steps:
|
steps:
|
||||||
- name: Check out source
|
- name: Check out source
|
||||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
@@ -140,28 +146,24 @@ jobs:
|
|||||||
- name: Select image tag
|
- name: Select image tag
|
||||||
id: image
|
id: image
|
||||||
env:
|
env:
|
||||||
CONFIGURED_IMAGE: ${{ vars.CONTAINER_IMAGE }}
|
|
||||||
EVENT_NAME: ${{ gitea.event_name }}
|
EVENT_NAME: ${{ gitea.event_name }}
|
||||||
GITEA_REF: ${{ gitea.ref }}
|
GITEA_REF: ${{ gitea.ref }}
|
||||||
GITEA_SHA: ${{ gitea.sha }}
|
GITEA_SHA: ${{ gitea.sha }}
|
||||||
run: |
|
run: |
|
||||||
publish=false
|
publish=false
|
||||||
image=labtimesheet
|
image="$REGISTRY/$IMAGE_NAME"
|
||||||
if [ "$EVENT_NAME" = "push" ] && [ "$GITEA_REF" = "refs/heads/main" ]; then
|
if [ "$EVENT_NAME" = "push" ] && [ "$GITEA_REF" = "refs/heads/main" ]; then
|
||||||
test -n "$CONFIGURED_IMAGE" || { echo "Repository variable CONTAINER_IMAGE is required" >&2; exit 1; }
|
|
||||||
publish=true
|
publish=true
|
||||||
image="$CONFIGURED_IMAGE"
|
|
||||||
fi
|
fi
|
||||||
echo "publish=$publish" >> "$GITHUB_OUTPUT"
|
echo "publish=$publish" >> "$GITHUB_OUTPUT"
|
||||||
echo "registry=${image%%/*}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "tag=$image:sha-${GITEA_SHA}-arm64" >> "$GITHUB_OUTPUT"
|
echo "tag=$image:sha-${GITEA_SHA}-arm64" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Log in to registry
|
- name: Log in to registry
|
||||||
if: steps.image.outputs.publish == 'true'
|
if: steps.image.outputs.publish == 'true'
|
||||||
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||||
with:
|
with:
|
||||||
registry: ${{ steps.image.outputs.registry }}
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
username: ${{ gitea.actor }}
|
||||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
- name: Build native ARM64 image
|
- name: Build native ARM64 image
|
||||||
@@ -179,28 +181,23 @@ jobs:
|
|||||||
needs: [amd64, arm64]
|
needs: [amd64, arm64]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Buildx
|
- name: Set up Buildx
|
||||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
||||||
|
|
||||||
- name: Resolve registry
|
|
||||||
id: image
|
|
||||||
env:
|
|
||||||
CONFIGURED_IMAGE: ${{ vars.CONTAINER_IMAGE }}
|
|
||||||
run: |
|
|
||||||
test -n "$CONFIGURED_IMAGE" || { echo "Repository variable CONTAINER_IMAGE is required" >&2; exit 1; }
|
|
||||||
echo "registry=${CONFIGURED_IMAGE%%/*}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Log in to registry
|
- name: Log in to registry
|
||||||
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||||
with:
|
with:
|
||||||
registry: ${{ steps.image.outputs.registry }}
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
username: ${{ gitea.actor }}
|
||||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
- name: Publish combined manifest
|
- name: Publish combined manifest
|
||||||
env:
|
env:
|
||||||
IMAGE: ${{ vars.CONTAINER_IMAGE }}
|
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
GITEA_SHA: ${{ gitea.sha }}
|
GITEA_SHA: ${{ gitea.sha }}
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools create \
|
docker buildx imagetools create \
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ target/
|
|||||||
.mvn/wrapper/maven-wrapper.jar
|
.mvn/wrapper/maven-wrapper.jar
|
||||||
!**/src/main/**/target/
|
!**/src/main/**/target/
|
||||||
!**/src/test/**/target/
|
!**/src/test/**/target/
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
### STS ###
|
### STS ###
|
||||||
.apt_generated
|
.apt_generated
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ Within a feature, create only layers it needs from `controller`, `model`, `model
|
|||||||
|
|
||||||
Preserve the domain boundaries: attendance time never derives Task work time; historical policies, memberships, leadership, creator/assignee attribution, and decisions do not silently move when current configuration changes.
|
Preserve the domain boundaries: attendance time never derives Task work time; historical policies, memberships, leadership, creator/assignee attribution, and decisions do not silently move when current configuration changes.
|
||||||
|
|
||||||
|
Membership-exit implementation must preserve two distinct paths. A pending exit keeps membership and existing Task rights active but excludes the target from new/self-assignment; the current/new Leader performs repeatable atomic multi-Task/one-recipient transfer batches before Mentor approval, and cancellation/rejection does not undo completed batches. Direct Mentor removal remains the atomic shortcut that transfers all unfinished Tasks to the current or replacement Leader. Completed Tasks keep the removed member's historical assignee name.
|
||||||
|
|
||||||
|
History UI must read the retained feature-owned rows already present. Project History covers memberships, leadership, invitations, exit decisions, completed/soft-deleted Tasks, comments, work logs, and stored attribution under AUTH-006 visibility. Admin-only Policy, Calendar, SMTP, and HolidayAPI History exposes non-secret domain metadata only. Do not add a generic audit/event-sourcing layer, Task-assignment-history table, or fabricated previous-assignee/status/edit timeline.
|
||||||
|
|
||||||
## Lombok is the default for Java boilerplate
|
## Lombok is the default for Java boilerplate
|
||||||
|
|
||||||
Lombok is already installed and configured as an annotation processor. Use it by default when it removes mechanical Java without hiding a business rule.
|
Lombok is already installed and configured as an annotation processor. Use it by default when it removes mechanical Java without hiding a business rule.
|
||||||
|
|||||||
+2
-4
@@ -58,12 +58,10 @@ Configure these repository settings:
|
|||||||
|
|
||||||
| Kind | Name | Value |
|
| Kind | Name | Value |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Variable | `CONTAINER_IMAGE` | Full image name, for example `git.sechmachine.io.vn/sechmachine/labtimesheet` |
|
|
||||||
| Variable | `ARM64_RUNNER_AVAILABLE` | `true` only while a trusted `ubuntu-latest-arm` runner is registered and online; otherwise omit it or set `false` |
|
| Variable | `ARM64_RUNNER_AVAILABLE` | `true` only while a trusted `ubuntu-latest-arm` runner is registered and online; otherwise omit it or set `false` |
|
||||||
| Secret | `REGISTRY_USERNAME` | Registry user allowed to publish this package |
|
| Secret | `REGISTRY_TOKEN` | Token for the triggering Gitea account with package read/write access |
|
||||||
| Secret | `REGISTRY_TOKEN` | Registry token with package write access |
|
|
||||||
|
|
||||||
`verify.yml` runs for every pull request and push. `container.yml` runs only when manually dispatched or when `main` is pushed, and it repeats verification before either architecture build. Manual runs build without publishing. A push to `main` publishes immutable `sha-<commit>` and convenience `main` tags.
|
The workflow publishes `git.sechmachine.io.vn/sechmachine/labtimesheet` and authenticates as the triggering Gitea account. `verify.yml` runs for every pull request and push. `container.yml` runs only when manually dispatched or when `main` is pushed, and it repeats verification before either architecture build. Manual runs build without publishing. A push to `main` publishes immutable `sha-<commit>` and convenience `main` tags.
|
||||||
|
|
||||||
When ARM64 is disabled, those canonical tags remain valid AMD64 images and the workflow succeeds. When it is enabled, the native ARM runner publishes an architecture tag and the final job replaces the canonical tags with a combined AMD64/ARM64 manifest. Gitea cannot discover an unavailable runner from inside an unscheduled job, so the repository variable is the deliberate availability gate.
|
When ARM64 is disabled, those canonical tags remain valid AMD64 images and the workflow succeeds. When it is enabled, the native ARM runner publishes an architecture tag and the final job replaces the canonical tags with a combined AMD64/ARM64 manifest. Gitea cannot discover an unavailable runner from inside an unscheduled job, so the repository variable is the deliberate availability gate.
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -17,10 +17,10 @@ web
|
|||||||
|
|
||||||
## Users
|
## Users
|
||||||
|
|
||||||
- **Admins** operate accounts, internship lifecycles, attendance policy, the global calendar, SMTP, HolidayAPI, and system configuration. They inspect Project and attendance progress but do not perform Mentor or Project Leader work.
|
- **Admins** operate accounts, internship lifecycles, attendance policy, the global calendar, SMTP, HolidayAPI, and system configuration. They inspect all Project and attendance progress/history read-only but do not perform Mentor or Project Leader work.
|
||||||
- **Mentors** own Projects, directly manage membership and leadership, decide membership exits, monitor Project and Intern progress, comment on Tasks, inspect attendance, and decide leave and missed-checkout corrections.
|
- **Mentors** own Projects, directly manage membership and leadership, decide membership exits, monitor Project and Intern progress/history, comment on Tasks, inspect attendance, and decide leave and missed-checkout corrections.
|
||||||
- **Interns** check in and out, request leave and missed-checkout corrections, respond to their own Project invitations, request/cancel their own Project exit, participate in multiple Projects, create self-assigned Tasks, perform assigned Tasks, comment, update their own assigned Task status, and record Task work.
|
- **Interns** check in and out, request leave and missed-checkout corrections, respond to their own Project invitations, request/cancel their own Project exit, participate in multiple Projects, create self-assigned Tasks when eligible, perform assigned Tasks, comment, update their own assigned Task status, record Task work, and inspect authorized Project history.
|
||||||
- A **Project Leader** is an Intern with a current leadership term for one Project. It is contextual authority, never a global account role. The Leader may invite eligible Interns, request a member's removal, and manage Task definitions/assignment inside that Project.
|
- A **Project Leader** is an Intern with a current leadership term for one Project. It is contextual authority, never a global account role. The Leader may invite eligible Interns, request a member's removal, manage Task definitions/assignment, and redistribute unfinished Tasks away from a pending exit target in confirmed batches.
|
||||||
- The product is reviewed and maintained by a university project team and its instructor or appointed maintainer.
|
- The product is reviewed and maintained by a university project team and its instructor or appointed maintainer.
|
||||||
|
|
||||||
## Product Purpose
|
## Product Purpose
|
||||||
@@ -46,13 +46,13 @@ The product joins attendance oversight and Project delivery without pretending t
|
|||||||
## Capabilities and Constraints
|
## Capabilities and Constraints
|
||||||
|
|
||||||
- Global account roles are exactly `ADMIN`, `MENTOR`, and `INTERN`, and are immutable after account creation.
|
- Global account roles are exactly `ADMIN`, `MENTOR`, and `INTERN`, and are immutable after account creation.
|
||||||
- Project membership is many-to-many and interval-based. The owning Mentor may add/remove directly and makes every exit decision; the current Leader may invite; only the intended authenticated Intern may accept/decline; members may request but cannot unilaterally leave.
|
- Project membership is many-to-many and interval-based. The owning Mentor may add/remove directly and makes every exit decision; the current Leader may invite; only the intended authenticated Intern may accept/decline; members may request but cannot unilaterally leave. Pending exit keeps existing rights but blocks new/self-assignment to the target; the Leader redistributes unfinished Tasks before approval, while direct Mentor removal retains its atomic automatic-transfer shortcut.
|
||||||
- Every `PLANNED` or `ACTIVE` Project has exactly one current Intern Leader. Any active member may create a Task assigned only to themselves; only the current Leader may create for another member or reassign broader Task work.
|
- Every `PLANNED` or `ACTIVE` Project has exactly one current Intern Leader. Any active member may create a Task assigned only to themselves; only the current Leader may create for another member or reassign broader Task work.
|
||||||
- Each Task has one current assignee. Only that assignee changes its status and records work.
|
- Each Task has one current assignee. Only that assignee changes its status and records work.
|
||||||
- Attendance uses server-time check-in and checkout. Effective-dated policy stores separate check-in and checkout grace periods, both defaulting to 30 minutes; with the default 15:30 end, normal checkout closes immediately after the inclusive 16:00:00 cutoff. Task work is a separate dated-minute record and never proves attendance.
|
- Attendance uses server-time check-in and checkout. Effective-dated policy stores separate check-in and checkout grace periods, both defaulting to 30 minutes; with the default 15:30 end, normal checkout closes immediately after the inclusive 16:00:00 cutoff. Task work is a separate dated-minute record and never proves attendance.
|
||||||
- Leave is full-day. Only frozen eligible workdays consume quota, and pending or approved requests reserve it.
|
- Leave is full-day. Only frozen eligible workdays consume quota, and pending or approved requests reserve it.
|
||||||
- Corrections apply only to missing checkout after the attendance row's historical checkout cutoff. Submission remains open through scheduled end plus 24 hours, and the Mentor then receives a separate 24-hour decision window.
|
- Corrections apply only to missing checkout after the attendance row's historical checkout cutoff. Submission remains open through scheduled end plus 24 hours, and the Mentor then receives a separate 24-hour decision window.
|
||||||
- Global attendance policy is effective-dated; historical attendance and leave allocations must not drift after later policy or calendar changes.
|
- Global attendance policy is effective-dated; historical attendance and leave allocations must not drift after later policy or calendar changes. Admin-only setting History tabs and authorized Project History read the retained domain rows already present; they never expose secrets or invent previous-assignee/status/edit timelines that are not stored.
|
||||||
- SMTP and HolidayAPI secrets are Admin-managed and encrypted with a deployment-provided master key. Email-dependent account actions fail closed when SMTP is unavailable; other domain actions retain in-app delivery.
|
- SMTP and HolidayAPI secrets are Admin-managed and encrypted with a deployment-provided master key. Email-dependent account actions fail closed when SMTP is unavailable; other domain actions retain in-app delivery.
|
||||||
- HTML, Excel, and PDF reports must agree on the same hand-checkable totals and render undefined denominators as `N/A`.
|
- HTML, Excel, and PDF reports must agree on the same hand-checkable totals and render undefined denominators as `N/A`.
|
||||||
- The product language is English in v1. Displayed business dates use `dd/MM/yyyy` and times use 24-hour local time.
|
- The product language is English in v1. Displayed business dates use `dd/MM/yyyy` and times use 24-hour local time.
|
||||||
@@ -75,7 +75,7 @@ The product joins attendance oversight and Project delivery without pretending t
|
|||||||
## Product Principles
|
## Product Principles
|
||||||
|
|
||||||
1. **Authorization follows stored context.** Global role alone is insufficient; ownership, membership, leadership, assignment, lifecycle, and record scope determine access.
|
1. **Authorization follows stored context.** Global role alone is insufficient; ownership, membership, leadership, assignment, lifecycle, and record scope determine access.
|
||||||
2. **History does not move.** Later policy, calendar, membership, invitation, exit decision, leadership, assignment, or assignee changes must not silently rewrite past results, Task creator attribution, or provenance.
|
2. **History does not move or pretend.** Later policy, calendar, membership, invitation, exit decision, leadership, assignment, or assignee changes must not silently rewrite past results, completed-Task assignee names, creator attribution, or provenance. History views expose only retained domain facts and non-secret metadata; they do not fabricate event timelines the schema never stored.
|
||||||
3. **Attendance and Project work stay distinct.** The product may report them together, but one never derives or proves the other.
|
3. **Attendance and Project work stay distinct.** The product may report them together, but one never derives or proves the other.
|
||||||
4. **Deadlines are enforced at every path.** Scheduled workers improve timeliness, while request-time guards preserve correctness when scheduling is late.
|
4. **Deadlines are enforced at every path.** Scheduled workers improve timeliness, while request-time guards preserve correctness when scheduling is late.
|
||||||
5. **Prefer explicit, reviewable operations.** Feature-owned controller/service/repository flows, constrained state transitions, focused integrations, and shared report datasets serve clarity over speculative machinery.
|
5. **Prefer explicit, reviewable operations.** Feature-owned controller/service/repository flows, constrained state transitions, focused integrations, and shared report datasets serve clarity over speculative machinery.
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ Projects, Tasks, and attendance. Iteration 1 is complete and was verified on
|
|||||||
The baseline schema includes later-workflow tables; table presence does not mean
|
The baseline schema includes later-workflow tables; table presence does not mean
|
||||||
the corresponding feature is complete.
|
the corresponding feature is complete.
|
||||||
|
|
||||||
- Iteration 2: Project invitations and approved membership exits, broader Project lifecycle transfers, Task edit/delete/reassignment and work logs, leave, missed-checkout corrections, notifications, schedulers, and complete metrics.
|
- Iteration 2: Project invitations; assisted membership exits with persistent readiness warnings and Leader-managed transfer batches before approval; the existing direct-removal automatic-transfer shortcut; Task edit/delete/reassignment and work logs; authorized Project History; Admin-only non-secret Policy/Calendar/SMTP/HolidayAPI History; leave, missed-checkout corrections, notifications, schedulers, and complete metrics.
|
||||||
- Iteration 3: HTML/XLSX/PDF report parity, Chart.js trends, remaining production security hardening, and operational backup/restore qualification.
|
- Iteration 3: HTML/XLSX/PDF report parity, Chart.js trends, remaining production security hardening, and operational backup/restore qualification.
|
||||||
- Mobile layouts are best-effort. Desktop is the supported interface target.
|
- Mobile layouts are best-effort. Desktop is the supported interface target.
|
||||||
|
|
||||||
|
|||||||
+178
@@ -0,0 +1,178 @@
|
|||||||
|
# Lab Timesheet Technology Stack
|
||||||
|
|
||||||
|
This document is the team reference for the technologies and development tools
|
||||||
|
used by Lab Timesheet. The five-person development team uses Windows 11 and
|
||||||
|
IntelliJ IDEA. Versions controlled by the repository must not be changed in one
|
||||||
|
developer's environment without a reviewed project-wide update.
|
||||||
|
|
||||||
|
## 1. Architecture
|
||||||
|
|
||||||
|
| Choice | Use | Rationale |
|
||||||
|
|---|---|---|
|
||||||
|
| Server-rendered modular monolith | One Spring Boot application organized by account, integration, Project, Task, attendance, notification, and reporting features | A single deployable application keeps transactions, authorization, testing, and deployment manageable for a small team while feature packages preserve clear ownership. |
|
||||||
|
| Spring MVC with Thymeleaf | Controllers return HTML pages rendered on the server | The product is a form- and workflow-heavy desktop web application. Server rendering avoids the extra API, SPA state, and authentication complexity of a separate frontend application. |
|
||||||
|
| Feature-first Java packages | Each feature owns its controllers, DTOs, entities, repositories, services, and exceptions | Related code stays together, while cross-feature access is limited to public services and DTOs. This supports the five-branch team workflow without duplicating database models. |
|
||||||
|
| Executable WAR | Maven packages the application as a WAR that can still run with `java -jar` | It works with the current Spring Boot deployment while keeping conventional servlet-container compatibility. |
|
||||||
|
| HTML sessions and CSRF protection | Spring Security manages authenticated browser sessions | The application is server-rendered. Session cookies and CSRF protection are simpler and safer here than introducing JWTs. |
|
||||||
|
|
||||||
|
The project deliberately does not use a SPA framework, JWT authentication,
|
||||||
|
microservices, Redis, Kafka, or a generic workflow engine. Those technologies
|
||||||
|
would add operational and development cost without solving a current need.
|
||||||
|
|
||||||
|
## 2. Team workstations
|
||||||
|
|
||||||
|
| Tool | Team baseline | Use | Rationale |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Windows | Windows 11 | Team development operating system | One shared OS baseline makes IDE, Docker, path, and command guidance reproducible for the student team. |
|
||||||
|
| IntelliJ IDEA | Current supported release | Main IDE for Java, Maven, Spring Boot, Thymeleaf, debugging, and test execution | IntelliJ has strong Spring and Java support and provides one consistent run/debug workflow for the team. |
|
||||||
|
| Eclipse Temurin JDK | Java 25 | Compile, test, and run the application | Java 25 is the project language baseline, and Temurin matches the JDK distribution used by CI and container builds. |
|
||||||
|
| IntelliJ annotation processing | Enabled for the project | Makes Lombok-generated constructors and accessors visible to the IDE | Maven already runs Lombok as an annotation processor. Enabling the same behavior in IntelliJ prevents false editor errors. |
|
||||||
|
| Git | Current supported release | Version control and the branch/worktree workflow | Git supports the five persistent feature branches, isolated fix branches, review, and traceable milestone commits. |
|
||||||
|
| PowerShell | Included with Windows 11 | Run Windows commands and `mvnw.cmd` | It is available on every team workstation and avoids requiring a separate shell for normal development. |
|
||||||
|
| OpenSSL | Current supported release | Generates the Base64 256-bit application master key | A standard cryptographic tool avoids inventing or manually typing security keys. Git for Windows or another trusted Windows package may provide it. |
|
||||||
|
| Microsoft Edge or Google Chrome | Current stable release | Manual desktop-browser checks and debugging | The product targets desktop browsers, and both provide standards-based developer tools for HTML, CSS, accessibility, storage, and network inspection. |
|
||||||
|
|
||||||
|
## 3. Java and build platform
|
||||||
|
|
||||||
|
| Technology | Version | Use | Rationale |
|
||||||
|
|---|---:|---|---|
|
||||||
|
| Java | 25 | Application language and runtime | Provides a modern supported Java baseline while keeping one version across local development, CI, and production. |
|
||||||
|
| Spring Boot | 4.1.0 | Application framework and dependency management | Supplies compatible Spring modules, production conventions, testing support, and a managed dependency set. |
|
||||||
|
| Maven Wrapper | Wrapper 3.3.4; Maven 3.9.16 | Java dependency resolution, compilation, tests, Javadoc, and packaging | The checked-in wrapper gives every Windows workstation and CI runner the same Maven version without a separate Maven installation. Use `mvnw.cmd` on Windows. |
|
||||||
|
| Javadoc with doclint | Java 25 toolchain | Validates generated API documentation | Documentation errors are caught during development and CI with the same JDK that compiles the application. |
|
||||||
|
| Lombok | Spring Boot-managed version | Removes mechanical constructors and accessors | Targeted Lombok annotations reduce boilerplate while explicit domain constructors, validation, state changes, and entity identity methods remain visible. |
|
||||||
|
| Spring Boot configuration processor | Spring Boot-managed version | Generates typed Spring configuration metadata during compilation | It improves configuration accuracy and IntelliJ assistance without adding runtime code. |
|
||||||
|
| Embedded/provided Tomcat | Spring Boot-managed version | Servlet runtime for the executable WAR | It is the standard Spring MVC runtime and requires no separate application server for development or the production image. |
|
||||||
|
|
||||||
|
Unless a row gives an explicit version, Java dependency versions are managed by
|
||||||
|
the Spring Boot 4.1.0 dependency set. This prevents individual libraries from
|
||||||
|
being upgraded into incompatible combinations.
|
||||||
|
|
||||||
|
## 4. Spring and Java dependencies
|
||||||
|
|
||||||
|
| Dependency | Use | Rationale |
|
||||||
|
|---|---|---|
|
||||||
|
| Spring Web MVC | Controllers, request binding, validation errors, and server-rendered routes | It matches the Thymeleaf form workflow and keeps browser navigation on the server. |
|
||||||
|
| Spring Security | Login, password hashing, sessions, CSRF, role checks, and security headers | Security rules stay in the established Spring filter and authorization model rather than custom code. |
|
||||||
|
| Spring Data JPA and Hibernate | Entity mapping, repositories, transactions, optimistic locking, and pessimistic locks | JPA removes routine persistence code while PostgreSQL and Flyway remain the schema authority. |
|
||||||
|
| Spring Validation / Jakarta Validation | Request DTO and configuration validation | Validation annotations provide consistent trust-boundary checks and actionable form errors. |
|
||||||
|
| Thymeleaf | HTML page and email-template rendering | Templates integrate directly with Spring MVC and work without a client-side framework. |
|
||||||
|
| Thymeleaf Spring Security extras | Role- and authentication-aware template rendering | Navigation and controls can reflect server authorization without duplicating role parsing. |
|
||||||
|
| Spring Mail | SMTP connectivity and email delivery | Uses the standard Jakarta Mail integration while SMTP settings remain Admin-managed application data. |
|
||||||
|
| Spring Boot Actuator | Liveness, readiness, and application health | Standard health endpoints support Docker health checks and production operations. |
|
||||||
|
| Spring Boot Flyway integration | Runs reviewed database migrations at startup | Database changes are ordered, repeatable, and validated before Hibernate mappings are used. |
|
||||||
|
| Flyway PostgreSQL support | PostgreSQL-specific migration support | The schema uses PostgreSQL features such as `btree_gist`, checks, partial indexes, and exclusion constraints. |
|
||||||
|
| PostgreSQL JDBC driver | Runtime database connection | It is the official Java driver for the selected database. |
|
||||||
|
| Spring Boot DevTools | Development-only restart support | Shortens the local feedback loop without becoming a production dependency. |
|
||||||
|
| Spring Boot Docker Compose support | Optional runtime integration | It is available for Spring tooling, although the documented development loop currently starts PostgreSQL and Mailpit explicitly. |
|
||||||
|
|
||||||
|
## 5. Database and persistence
|
||||||
|
|
||||||
|
| Technology | Version | Use | Rationale |
|
||||||
|
|---|---:|---|---|
|
||||||
|
| PostgreSQL | 18.4 | Development, test, and production database | The domain requires reliable transactions, constraints, date/time types, partial indexes, exclusion constraints, and strong concurrency behavior. Using the same engine everywhere avoids H2-specific surprises. |
|
||||||
|
| Flyway | Spring Boot-managed version | Versioned schema migrations | Flyway makes the reviewed SQL schema reproducible on an empty database and safe to validate in CI. |
|
||||||
|
| Hibernate schema validation | `ddl-auto=validate` | Confirms entity mappings match the migrated schema | Hibernate must not silently create or alter production tables; Flyway remains authoritative. |
|
||||||
|
| PostgreSQL `btree_gist` | Database extension | Supports exclusion constraints such as overlapping leave prevention | The database can reject invalid concurrent data even when two application requests race. |
|
||||||
|
|
||||||
|
## 6. Frontend stack
|
||||||
|
|
||||||
|
| Technology | Version | Use | Rationale |
|
||||||
|
|---|---:|---|---|
|
||||||
|
| Thymeleaf | Spring Boot-managed version | Page layouts, fragments, forms, validation messages, and role-aware navigation | It keeps rendering and authorization close to the Spring MVC application. |
|
||||||
|
| HTML5 | Browser standard | Semantic forms, tables, native dialogs, and accessible page structure | Native elements reduce custom JavaScript and provide built-in keyboard and form behavior. |
|
||||||
|
| Tailwind CSS | 4.3.3 | Compiled design tokens and utility-based styling | It supports the shared light/dark desktop design without shipping a runtime CSS framework. |
|
||||||
|
| Tailwind CLI | 4.3.3 | Builds the committed production CSS asset | The small CLI is sufficient; no frontend bundler or SPA toolchain is needed. |
|
||||||
|
| Lucide Static | 1.27.0 | Local SVG icon sprite | Icons are available offline, inherit theme color, and do not require React or an icon CDN. |
|
||||||
|
| Native JavaScript modules | Browser standard | Small interactions such as theme selection, sidebar state, dialogs, and local search | The current interactions do not justify a client-side application framework. |
|
||||||
|
| Node.js | 24.x | Frontend build scripts and JavaScript tests | Node 24 is the pinned LTS toolchain used consistently by developers, CI, and the Docker build. |
|
||||||
|
| npm | 11.x | Reproducible frontend dependency installation | `npm ci` and the committed lockfile install exactly the reviewed dependency graph. |
|
||||||
|
|
||||||
|
## 7. External services and integrations
|
||||||
|
|
||||||
|
| Service or standard | Use | Rationale |
|
||||||
|
|---|---|---|
|
||||||
|
| SMTP | Activation, password recovery, and ordinary workflow email | SMTP is widely supported and allows the application to work with university or other approved mail providers. Configuration is tested and activated through the Admin console. |
|
||||||
|
| Mailpit | Development SMTP server and web inbox | Mailpit captures messages locally so developers never send test activation or recovery email to real users. The development image is pinned to `axllent/mailpit:v1.27.4`. |
|
||||||
|
| HolidayAPI | Optional Vietnam holiday preview/import | It reduces manual holiday entry while imported dates remain a preview and the Admin's local day-off decision remains authoritative. |
|
||||||
|
| AES-256-GCM from the JDK | Encrypts stored SMTP and HolidayAPI secrets | Authenticated encryption protects confidentiality and detects modification without adding another cryptography dependency. |
|
||||||
|
| HTTPS reverse proxy | Production TLS termination and forwarding | The application image stays focused on Java while an operator-managed proxy handles certificates and the public HTTPS endpoint. |
|
||||||
|
|
||||||
|
## 8. Testing tools
|
||||||
|
|
||||||
|
| Tool | Use | Rationale |
|
||||||
|
|---|---|---|
|
||||||
|
| JUnit Jupiter | Unit and integration test framework | It is the standard JUnit 5 programming model supplied by Spring Boot and works with Maven Surefire and IntelliJ. |
|
||||||
|
| Maven Surefire | Maven/Spring Boot-managed version | Discovers and runs the Java test suite | The same Maven command behaves consistently in IntelliJ terminals, PowerShell, and CI. |
|
||||||
|
| Spring Boot Test | Application-context and integration testing | It verifies real Spring configuration, dependency injection, transactions, and profile behavior. |
|
||||||
|
| Focused Spring Boot test starters | Data JPA, Flyway, Mail, Security, Thymeleaf, Validation, and Web MVC test support | Each test slice receives the framework support it actually exercises instead of one unrelated test environment. |
|
||||||
|
| Spring MVC Test / MockMvc | Controller, security, validation, and Thymeleaf route tests | HTTP behavior can be tested quickly without launching a separate browser process. |
|
||||||
|
| Spring Security Test | Authenticated role and CSRF test support | Tests can prove allowed and denied behavior using the same security filter chain. |
|
||||||
|
| Mockito | Test doubles for external or out-of-scope collaborators | It isolates a focused unit or MVC slice without replacing the database behavior being tested. |
|
||||||
|
| Testcontainers | Spring Boot-managed version | Starts disposable infrastructure for integration tests | Tests use real PostgreSQL 18.4 without depending on a developer's database or leaving shared state behind. |
|
||||||
|
| Testcontainers PostgreSQL | PostgreSQL 18.4 test container integration | It validates Flyway SQL, JPA mappings, constraints, locking, and concurrency against the production database engine. |
|
||||||
|
| Node built-in test runner | Frontend asset and workflow contract tests | The required JavaScript checks run without adding another test framework. |
|
||||||
|
| Playwright | Automated desktop-browser end-to-end journeys | Playwright provides repeatable Chromium-based tests for bootstrap, login, role navigation, Projects, Tasks, attendance, and accessibility-sensitive workflows required by the instructor. |
|
||||||
|
| Manual Edge/Chrome journeys | Exploratory and final visual checks | Manual checks still catch layout, focus, contrast, and real-browser integration issues that focused automated tests may not explain clearly. |
|
||||||
|
| Markdown evidence records | RED/GREEN and affected-suite evidence under `docs/tests/` | Each feature change remains traceable to requirements, commands, expected results, and test boundaries. |
|
||||||
|
|
||||||
|
## 9. Reporting technologies
|
||||||
|
|
||||||
|
These tools are approved for the reporting iteration. They must be added with
|
||||||
|
reviewed, pinned versions when their corresponding feature is implemented.
|
||||||
|
|
||||||
|
| Technology | Approved baseline | Use | Rationale |
|
||||||
|
|---|---:|---|---|
|
||||||
|
| Chart.js | 4.5.1 | Meaningful attendance and Project trend charts | It provides accessible, lightweight charts without changing the server-rendered architecture; every chart also requires a text or table alternative. |
|
||||||
|
| Apache POI XSSF | Compatible 5.5.x | Excel `.xlsx` exports | POI is the established Java library for native Excel workbooks and supports typed cells and formatting. |
|
||||||
|
| OpenPDF `openpdf-html` | Compatible 3.0.x | PDF generation from a dedicated print-safe template | It keeps PDF generation inside Java and supports an embedded Unicode font for Vietnamese content. |
|
||||||
|
|
||||||
|
## 10. Containers and production delivery
|
||||||
|
|
||||||
|
| Technology | Version or baseline | Use | Rationale |
|
||||||
|
|---|---:|---|---|
|
||||||
|
| Docker Desktop | Current supported Windows release using Linux containers | Development infrastructure, Testcontainers, and local production-image checks | It provides the Docker Engine expected by PostgreSQL, Mailpit, Testcontainers, and multi-stage builds on Windows 11. |
|
||||||
|
| Docker Compose | v2.20 or newer | Production example with bundled or external PostgreSQL | One documented file supports both deployment topologies while retaining persistent database storage. |
|
||||||
|
| Docker BuildKit / Buildx | Current workflow-pinned release | Multi-stage and multi-architecture image builds | Buildx produces native Linux AMD64 and optional ARM64 images with reproducible build stages. |
|
||||||
|
| Node Alpine image | Node 24, digest-pinned | Builds Tailwind and Lucide assets | Frontend tools do not remain in the final Java runtime image. |
|
||||||
|
| Eclipse Temurin images | Java 25 JDK and JRE, digest-pinned | Builds the WAR and runs the production application | Separate build and runtime images reduce the final image size and match the Java baseline. |
|
||||||
|
| PostgreSQL image | 18.4, digest-pinned | Optional bundled production database | Digest pinning prevents an image tag from silently changing during deployment. |
|
||||||
|
| OCI image registry | Gitea package registry | Stores immutable application images | Commit-SHA tags make a deployed version identifiable and allow a controlled rollback. |
|
||||||
|
|
||||||
|
The final application container runs as non-root UID/GID `10001`, uses a
|
||||||
|
read-only root filesystem in Compose, drops Linux capabilities, and exposes
|
||||||
|
Actuator readiness and liveness checks.
|
||||||
|
|
||||||
|
## 11. Source control and CI/CD
|
||||||
|
|
||||||
|
| Tool | Use | Rationale |
|
||||||
|
|---|---|---|
|
||||||
|
| Gitea | Git hosting, review, Actions, and OCI package registry | One project-owned platform stores source, reviews changes, runs checks, and publishes production images. |
|
||||||
|
| Gitea Actions | Verification on every pull request and push | CI repeats frontend, Java, PostgreSQL, Javadoc, generated-asset, and whitespace checks outside a developer workstation. |
|
||||||
|
| Container workflow | Manual dispatch or `main` push only | Image builds are expensive and potentially publish artifacts, so they run only after an internal verification job and never for ordinary feature branches or pull requests. |
|
||||||
|
| `actions/checkout` | 7.0.1, immutable SHA pin | Checks out source without retaining push credentials | An immutable pin prevents a moving action tag from changing CI behavior unexpectedly. |
|
||||||
|
| `actions/setup-java` | 5.7.0, immutable SHA pin | Installs Temurin Java 25 and manages the Maven cache | CI uses the same Java baseline as the team and production build. |
|
||||||
|
| `actions/setup-node` | 7.0.0, immutable SHA pin | Installs Node 24 and manages the npm cache | CI uses the same frontend toolchain as the lockfile and Docker build. |
|
||||||
|
| Docker Buildx action | 4.2.0, immutable SHA pin | Prepares multi-architecture image building | It supports native AMD64 and optional native ARM64 production builds. |
|
||||||
|
| Docker Login action | 4.6.0, immutable SHA pin | Authenticates only publication jobs to the registry | Registry credentials stay out of scripts and are used only when publishing is authorized. |
|
||||||
|
| Docker Build Push action | 7.3.0, immutable SHA pin | Builds and publishes OCI images | It provides one reviewed image-build path for both supported Linux architectures. |
|
||||||
|
|
||||||
|
## 12. Configuration and source-of-truth files
|
||||||
|
|
||||||
|
| File | Controls |
|
||||||
|
|---|---|
|
||||||
|
| `pom.xml` | Java version, Spring Boot version, Java dependencies, packaging, and annotation processors |
|
||||||
|
| `.mvn/wrapper/maven-wrapper.properties` | Maven Wrapper and Maven distribution |
|
||||||
|
| `package.json` and `package-lock.json` | Node/npm baseline and exact frontend dependencies |
|
||||||
|
| `src/main/resources/application*.yaml` | Shared, development, and production Spring configuration |
|
||||||
|
| `src/main/resources/db/migration/` | Flyway database schema history |
|
||||||
|
| `Dockerfile` | Production multi-stage application image |
|
||||||
|
| `compose.yaml` | Production application and optional PostgreSQL deployment example |
|
||||||
|
| `.gitea/workflows/` | Verification and container publication workflows |
|
||||||
|
| `DEVELOPMENT.md` | Windows/IDE-oriented local setup and run instructions |
|
||||||
|
| `TESTING.md` | Test commands, TDD rules, and evidence format |
|
||||||
|
| `DEPLOYMENT.md` | Production container configuration and operation |
|
||||||
|
|
||||||
|
When documentation and a build file disagree about an installed version, the
|
||||||
|
build file and lockfile are authoritative. Update this document in the same
|
||||||
|
reviewed change whenever the selected stack changes.
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Assisted Exit Transfer and History Documentation Plan
|
||||||
|
|
||||||
|
**Status:** Documentation update only. No application or schema implementation is authorized by this record.
|
||||||
|
**Date:** 20 August 2026
|
||||||
|
|
||||||
|
## Deliverables
|
||||||
|
|
||||||
|
1. Amend the existing `AUTH`, `PRJ`, `TSK`, `ATT`, `CAL`, `INT`, `UI`, and `DB` rows without adding requirement IDs.
|
||||||
|
2. Synchronize the explained and very-simple teaching copies.
|
||||||
|
3. Update `UC-04`, `UC-05`, `UC-06`, and `UC-14`, required workflow pages, and regenerate the SRS from its generator.
|
||||||
|
4. Update `PRODUCT.md`, `.agents/PROJECT_PLAN.md`, `AGENTS.md`, and `README.md` with the locked boundary and Iteration 2 ownership.
|
||||||
|
5. Add the append-only requirements update manifest.
|
||||||
|
6. Preserve both DDL files, both Mermaid structures, all mockup/reference assets, and `.DS_Store` byte-for-byte.
|
||||||
|
|
||||||
|
## Validation gates
|
||||||
|
|
||||||
|
- Exactly 260 unique requirement rows in authoritative, explained, simple, and generated SRS catalogues.
|
||||||
|
- Exactly 14 SRS use cases.
|
||||||
|
- Exactly 23 documented tables and 56 named foreign-key relationships; no DDL byte change.
|
||||||
|
- Generated SRS agrees with the canonical requirement rows and updated use cases/workflow pages.
|
||||||
|
- All local Markdown links resolve.
|
||||||
|
- Protected DDL/mockup/reference hashes and `.DS_Store` hash match the pre-update snapshot.
|
||||||
|
- `git diff --check` passes.
|
||||||
|
|
||||||
|
## Non-goals
|
||||||
|
|
||||||
|
No Java, Flyway, SQL, Mermaid structure, mockup, frontend asset, branch, commit, push, or deployment change is part of this task.
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# Assisted Exit Transfer and History Design
|
||||||
|
|
||||||
|
**Status:** Approved documentation baseline; application implementation remains Iteration 2 work.
|
||||||
|
**Date:** 20 August 2026
|
||||||
|
**Authority:** Current primary-implementor decision, applied through existing requirement IDs.
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Define a safe, understandable way to prepare a member's requested Project exit and expose useful retained history without changing the approved database structure.
|
||||||
|
|
||||||
|
## Assisted pending exit
|
||||||
|
|
||||||
|
A pending request keeps membership, existing assignments, and existing Task rights active. The target cannot receive a newly created/reassigned Task or create a self-Task. Every authorized Project viewer sees one readiness state: replacement Leader required, unfinished Task count, or ready for Mentor decision.
|
||||||
|
|
||||||
|
When the target is Leader, the owning Mentor appoints the replacement first. The current/new Leader then uses a right-side drawer to select multiple unfinished `TODO`, `IN_PROGRESS`, or `BLOCKED` Tasks and one eligible active current member. One confirmation commits one immediate all-or-none batch. The Leader repeats until no unfinished Tasks remain.
|
||||||
|
|
||||||
|
Cancellation or rejection restores the target's new-assignment eligibility but does not undo completed transfer batches. Approval is allowed only when the target is no longer Leader and owns zero unfinished Tasks; request approval and membership closure then commit atomically.
|
||||||
|
|
||||||
|
## Direct Mentor removal
|
||||||
|
|
||||||
|
Direct removal remains the existing atomic shortcut. An ordinary member's unfinished Tasks transfer to the current Leader. Removing the current Leader requires a replacement and transfers unfinished Tasks to that replacement. Completed Tasks never move and continue to display the removed Intern's retained name.
|
||||||
|
|
||||||
|
## History views
|
||||||
|
|
||||||
|
One Project History tab reads retained feature-owned records for memberships, leadership, invitations, exit decisions, completed and soft-deleted Tasks, comments, work logs, and stored attribution. Admin sees all Projects read-only; the owning Mentor and current members see authorized open Projects; removed members regain read-only Project history only after completion.
|
||||||
|
|
||||||
|
Task history shows creator, current/final assignee, status/dates, comment/work-log authors, and deletion attribution. It does not claim previous-assignee or edit/status-event timelines that the schema does not store.
|
||||||
|
|
||||||
|
Admin-only read-only History tabs cover Attendance Policy, Calendar, SMTP, and HolidayAPI. They show user-meaningful non-secret metadata and never expose tokens, ciphertext/nonces, passwords, API keys, master-key material, bootstrap state, or internal retry records.
|
||||||
|
|
||||||
|
## Persistence boundary
|
||||||
|
|
||||||
|
No table, foreign key, DDL statement, or Mermaid entity changes. The existing 23 tables and 56 foreign keys already retain the required domain records. `GOV-009` remains authoritative: no generic audit/event-sourcing or Task-assignment-history table.
|
||||||
|
|
||||||
|
## Iteration ownership
|
||||||
|
|
||||||
|
- `work/tasks`: pending-target assignment exclusion, atomic batch transfer, direct-removal transfer helper, unfinished count, and retained Task projection.
|
||||||
|
- `work/projects`: exit readiness, Leader replacement order, approval guard/closure, direct-removal orchestration, and Project-history authorization.
|
||||||
|
- `work/attendance`: policy/calendar retained-history queries.
|
||||||
|
- `work/platform`: non-secret SMTP/HolidayAPI revision-history queries.
|
||||||
|
- `work/reports-ui`: persistent warning, transfer drawer, Project History, and Admin-setting History tabs.
|
||||||
|
|
||||||
|
## Acceptance focus
|
||||||
|
|
||||||
|
Tests must cover replacement-before-transfer, a newly joined eligible recipient, pending-target exclusion, repeatable batches, cancel/reject without rollback, zero-unfinished approval guard, direct-removal atomic transfer, completed-name retention, every history role boundary, and secret redaction.
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# Test Evidence: Gitea container registry authentication
|
||||||
|
|
||||||
|
- **Test type:** Integration
|
||||||
|
- **Requirement IDs:** `OPS-012`, `OPS-016`, `OPS-017`
|
||||||
|
- **Scenario IDs:** `AC-OPS-004`
|
||||||
|
- **Test class/method:** `src/test/js/delivery-contract.test.mjs` — `container workflow runs only manually or on main and verifies before either image build`
|
||||||
|
- **Implementation commit:** `4dd9f96a231316ce2c14755157a380a2123c2f0b`
|
||||||
|
|
||||||
|
## Protected behavior
|
||||||
|
|
||||||
|
A push to `main` publishes `git.sechmachine.io.vn/sechmachine/labtimesheet` by authenticating the triggering Gitea account with the repository `REGISTRY_TOKEN`. Publication does not depend on separately configured image-name or username settings.
|
||||||
|
|
||||||
|
## Test method
|
||||||
|
|
||||||
|
The dependency-free Node contract reads the committed workflow and checks its fixed registry/image coordinates, actor-based username, token secret, and absence of the obsolete `CONTAINER_IMAGE` and `REGISTRY_USERNAME` settings. Ruby's YAML parser separately checks workflow syntax.
|
||||||
|
|
||||||
|
## Hand-derived expected result
|
||||||
|
|
||||||
|
The repository and package location are stable project facts. Therefore the workflow needs one credential only: a token belonging to the triggering actor with package read/write permission. Manual dispatch still builds without publishing; only a `main` push logs in and publishes.
|
||||||
|
|
||||||
|
## RED
|
||||||
|
|
||||||
|
**Command**
|
||||||
|
|
||||||
|
```text
|
||||||
|
env PATH=/opt/homebrew/opt/node@24/bin:/usr/bin:/bin node --test src/test/js/delivery-contract.test.mjs
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
4 tests ran: 3 passed, 1 failed. The container contract could not find the fixed registry/image or actor-based login. Real Gitea Container run 179 independently failed before registry login with "Repository variable CONTAINER_IMAGE is required", so REGISTRY_TOKEN was never used.
|
||||||
|
```
|
||||||
|
|
||||||
|
## GREEN
|
||||||
|
|
||||||
|
**Command**
|
||||||
|
|
||||||
|
```text
|
||||||
|
env PATH=/opt/homebrew/opt/node@24/bin:/usr/bin:/bin node --test src/test/js/delivery-contract.test.mjs
|
||||||
|
ruby -e 'require "yaml"; YAML.safe_load(File.read(".gitea/workflows/container.yml"), aliases: true); puts "container workflow YAML: OK"'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observed result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
Delivery contract: 4 tests, 4 passed. Container workflow YAML: OK.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Affected suite
|
||||||
|
|
||||||
|
**Command and result**
|
||||||
|
|
||||||
|
```text
|
||||||
|
git diff --check
|
||||||
|
! rg -n 'CONTAINER_IMAGE|REGISTRY_USERNAME' .gitea/workflows/container.yml DEPLOYMENT.md
|
||||||
|
|
||||||
|
Both checks passed. Application tests were deliberately not repeated because the change is limited to workflow metadata, its contract test, and deployment guidance; the container workflow retains its mandatory verify job before building.
|
||||||
|
```
|
||||||
|
|
||||||
|
## External-test boundaries
|
||||||
|
|
||||||
|
Local checks do not authenticate to the private registry. The first `main` push containing this change is the production-shaped check of `REGISTRY_TOKEN`, package permissions, and registry publication.
|
||||||
@@ -64,6 +64,11 @@ test("container workflow runs only manually or on main and verifies before eithe
|
|||||||
assert.match(workflow, /sha-\$\{GITEA_SHA\}-amd64/);
|
assert.match(workflow, /sha-\$\{GITEA_SHA\}-amd64/);
|
||||||
assert.match(workflow, /sha-\$\{GITEA_SHA\}-arm64/);
|
assert.match(workflow, /sha-\$\{GITEA_SHA\}-arm64/);
|
||||||
assert.match(workflow, /imagetools create/);
|
assert.match(workflow, /imagetools create/);
|
||||||
|
assert.match(workflow, /REGISTRY: git\.sechmachine\.io\.vn/);
|
||||||
|
assert.match(workflow, /IMAGE_NAME: sechmachine\/labtimesheet/);
|
||||||
|
assert.match(workflow, /username: \$\{\{ gitea\.actor \}\}/);
|
||||||
|
assert.match(workflow, /password: \$\{\{ secrets\.REGISTRY_TOKEN \}\}/);
|
||||||
|
assert.doesNotMatch(workflow, /CONTAINER_IMAGE|REGISTRY_USERNAME/);
|
||||||
assert.doesNotMatch(workflow, /ssh|DEPLOY_HOST|DEPLOY_KEY/i);
|
assert.doesNotMatch(workflow, /ssh|DEPLOY_HOST|DEPLOY_KEY/i);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user