Skip to content

feat: pin and unpin a commit from the signed API - #829

Open
RaphaelFakhri wants to merge 2 commits into
dev-null-sh:productionfrom
RaphaelFakhri:feat/api-commit-pin
Open

RaphaelFakhri wants to merge 2 commits into
dev-null-sh:productionfrom
RaphaelFakhri:feat/api-commit-pin

Conversation

@RaphaelFakhri

@RaphaelFakhri RaphaelFakhri commented Oct 20, 2026 •

Copy link
Copy Markdown

Lets the mobile app pin a commit to the user's profile and unpin it, the way the web's Pin does (#90). The app (NativePHP/dev-null-app) already shows the pinned commit, but the API has no route to change it.

Endpoints

PUT /api/v1/commits/{id}/pin and DELETE /api/v1/commits/{id}/pin, signed, no body.

  • 200 with the commit as GET /api/v1/commits/{id} shows it, so the app gets the new is_pinned, the same way the star endpoints answer.
  • Same rules as the web, through the same UpdateCommitPinRequest, DeleteCommitPinRequest, UpdateCommitPin and DeleteCommitPin: only the user's own top-level commits, pending or rejected included. Pinning another commit replaces the pin, and unpinning an older commit leaves a newer pin alone.
  • 403 for someone else's commit or a reply, 404 for a deleted or unknown commit, 401 without a signature.
  • throttle:pins (20 a minute), shared with the web.

The knowledge base no longer lists pinning as web-only.

Tests

tests/Feature/Controllers/Api/CommitPinControllerTest.php covers pin, unpin, replacing a pin, a stale unpin, the response shape, the 403/404/401 cases and the rate limit. All 16 tests fail without the change and pass with it.

Summary by CodeRabbit

  • New Features
    • Signed-in users can pin a commit to their profile or remove an existing pin through the API.
    • Pinning another user’s commit or a reply is not allowed. A new pin replaces the previous one, and requests to remove a stale pin are handled safely.
    • Requests are rate-limited.

@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1f8402aa-ec95-4b92-a61f-3fac3004e560
Commits

Reviewing files that changed from the base of the PR and between 8438a32 and b19550b.

Files selected for processing: 4
  • KNOWLEDGE_BASE.md
  • app/Http/Controllers/Api/CommitPinController.php
  • routes/api.php
  • tests/Feature/Controllers/Api/CommitPinControllerTest.php

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Walkthrough

The signed API now supports pinning and unpinning a user’s commit through authenticated, throttled endpoints. The controller invokes the matching pin action and returns the commit page representation. Feature tests cover responses, pin state, authorization, missing commits, unsigned requests, and rate limiting.

Changes: Commit pin API

Layer / File(s) Summary
Pin endpoints and response
app/Http/Controllers/Api/CommitPinController.php, routes/api.php, KNOWLEDGE_BASE.md
The controller invokes the pin or unpin action and returns a CommitResource. Authenticated, throttled routes expose both operations. The signed API capability list now includes commit pinning and unpinning.
Endpoint behavior tests
tests/Feature/Controllers/Api/CommitPinControllerTest.php
Feature tests cover successful operations, replacement and stale unpin requests, authorization, missing commits, unsigned requests, and rate limiting.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant APIClient
  participant APIRoute
  participant CommitPinController
  participant UpdateCommitPin
  participant CommitPageQuery
  APIClient->>APIRoute: Send authenticated PUT request
  APIRoute->>CommitPinController: Call update
  CommitPinController->>UpdateCommitPin: Pin current user's commit
  CommitPinController->>CommitPageQuery: Build commit page for user
  CommitPageQuery-->>APIClient: Return CommitResource
Loading

Possibly related PRs

  • dev-null-sh/dev-null.sh#1168: Changes how profile-pinned commits are retrieved, which connects to this PR’s API operations that update the same pin state.

Suggested reviewers: simonhamp

Merge Risk: Minimal · up to b1955

The new pin and unpin endpoints have no identified issue requiring correction before merge.

Security architecture risk: Minimal · up to b1955

The endpoints reuse existing signed-device authentication, ownership checks and atomic pin updates. Their effects remain limited to the caller’s own top-level commits. No material security regression was identified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The new operation lets an approved signed device change its owner’s profile pin. The attacker-controlled commit identifier cannot select another user’s pin row: authorization requires commit ownership and a top-level commit, and persistence is keyed to the authenticated user.

Trust Boundaries and Controls

  • observed — The routes sit inside mandatory signed-request authentication and the versioned API throttle group. Authentication establishes the approved device owner as the current user; the shared pins limiter permits 20 operations per minute keyed by user.

Resilience and Maintainability Implications

  • inferred — Pinning replaces one authenticated user’s reference in a single update. Unpinning atomically clears it only when it still matches the requested commit, protecting a replacement from a stale DELETE. Repeated operations converge without competing writes; competing pins remain last-writer-wins. These persistence semantics predate the API caller.
Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 3 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: adding commit pinning and unpinning to the signed API.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 3 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant