Repository navigation
codemap v0.1.3
Fixes for the issues reported through report_wrong_answer (#3–#9):
api_usage: a variable URL prefix with known values (kind === 'x' ? 'area/x' : 'area', also through a small helper function or a local constant) is expanded and each full URL matched; on irems-sg this resolved 45 of 64 unresolved calls. Suggestions for calls that stay unresolved are ranked by how many words of the URL tail match (#8).api_usage: method spoofing is read from a request body in a variable, a helper's returned object,payload._method = 'PUT'andform.append('_method', 'PUT')(#3).api_usage: a call no longer matches a route by crossing wildcards (/widgets/{}/archiveagainstwidgets/history/{widgetId}): it is reported as having no route (#5).- Routes registered by Laravel Passport (
oauth/token,oauth/authorize, …) and Sanctum (sanctum/csrf-cookie) are known without artisan mode (#4). composer.lockand other JSON files without a.jsonname are no longer read as JavaScript (#6).- Every tool refuses unknown arguments and names the accepted ones (
uri→uri_contains); so doesverify'sclaims(#7). - Wrong-answer report examples may use Laravel's standard app names (
AuthServiceProvider,App\Providers, …) and any class name declared by an installed package (#9).
New, from the feature requests (#10–#15):
- Routes registered by packages are known without artisan mode: Sanctum, Broadcasting (
broadcasting/auth), Fortify (following the features enabled inconfig/fortify.php), Horizon, Telescope, Pulse, Cashier (stripe/webhook) and Livewire (v2 and v3), with prefixes from their config files; Passport follows its version (automatic from v11 unlessignoreRoutes()) (#10). get_schemacan read tables and columns from a live database ([[databases]] schema = "live": information_schema for MySQL / MariaDB and PostgreSQL, pragma for SQLite, read-only, re-read at most every 10 minutes) or from a structure dump (dump = "file.sql"). Each column says where it comes from (source), and differences from the migrations are kept asdrift(#11).api_usagechecks what a call sends against what the action accepts: the Form Request'srules(), an inlinevalidate(), or the fields it reads (also in the controller's helper methods). New findingsmissing_requiredandunknown_field(status: payload), with the evidence; payloads built through spreads or helpers arepayload_unchecked, not guessed (#12).api_usagetakesgit_changes/changed_files(only the calls the change touches, including calls to backend routes whose route file or controller changed) andnew_only(hide findings saved by the newcodemap baseline).codemap check api [--changed]prints new findings and exits 1 on a new missing or wrong-method call, for CI and pre-commit hooks (#13).- Fields findings carry
evidence: where the response shape came from (Resource and itstoArrayfile:line, or the action'sreturn), every key it returns with conditional ones marked, and the paths the frontend read; brief answers name the shape too (#14). - A generated stress project (4,000 routes, 300 modules) is part of the tests; when a prefix is not expanded, the reason says whether a limit was hit or the value comes from code codemap does not follow (#15).
Fixes from the dev-build retest (17 Oct):
_methodspoofing follows conditions and scope:if (editing) payload._method = 'PATCH'makes the call "POST or PATCH" (either method fits), a helper that sets it under a parameter is decided by the argument at each call (widgetForm(record, false)stays POST), and a same-named variable in another function no longer inherits it. This was a regression in the #3 fix.- A payload copied into
FormDatawithObject.entries(…).forEach(…)orfor … of Object.entries(…), also through a localappendhelper, carries the object's keys. A body handed to other code, or one whose keys can't be read, is unchecked instead of "sends nothing". accepts_atfor rules in a controller helper names thevalidate()line and the call:NoteController.php:28 (in project(), called at line 14); it never says:0.- Less noise from the payload check: unread query parameters of a GET (or of a call with an unknown method) are a note (
unknown_query_note, listed withstatus: "payload_all"); nounknown_fieldwhen the payload was not fully followed; a missing required field and an unknown sent field on one call are reported aspossible_rename(unit_id → tenant_id);pageandcursorare accepted only when the action or a helper paginates. The evidence sayssends_completeandaccepts_completeseparately.
Fixes for two more reports (17 Oct):
- A URL value with a small known choice anywhere in the template is expanded and each full URL matched, including a parameter typed as a string union or an alias of one (
`/${kind}-permit/${id}`withkind: PermitKind,type PermitKind = 'loading' | 'unloading'). When none of the full URLs has a route, the call is reported as missing rather than matched loosely. - A variable inside a URL segment stands for one word:
{}-permitno longer fitsspfm-work-permit. _methodspoofing across files: a function that posts a body parameter takes the method its callers pass in that argument (invitationAction(id, 'void', { …, _method: 'PUT' })in another file makes it "POST or PUT"), and a body built by an imported helper (also copied intoFormData) takes the method that helper sets.
Fixes from the accuracy check on 9d73973 (17 Oct):
- More
_methodspoofing is followed: a caller that builds the body with a helper (inline or through a variable), a function that spreads its body parameter into a new body ({ ...record, reason }) or converts it (toFormData(payload)), Vue 2 component state (this.record._method = 'PATCH'then postingthis.recordorjsonFormData(this.record)), and?_method=PUTin the URL. On the test apps, wrong-method findings went from 6 to 3 and from 25 to 20, the ones checked by hand as real. - Calls to imported functions from packages (
reactive,ref) no longer count as body helpers; facts from both script blocks of a.vuefile are kept. - URLs naming a scaffold placeholder (
/_api_url_/{},/unitURL) get their ownplaceholderstatus instead ofmissing, and do not failcodemap check api. - A call whose URL has several known values says which ones have no route (
variants_without_route), also when another one matched; values from a component's computed property (this.reportSegment) are expanded. - A broken call inside an object's method that nothing calls (
billingDraftApi.post) is marked as dead code. - URL variants are built per value of the variables the URL depends on, so one variable that decides two parts (
${kind}${kind === 'rates' ? '/bulk' : ''}) only gives the URLs it can make. When a part cannot be tied to a known value, its URLs are tried but never reported as missing.
Also:
- Two folders of one repository (a monorepo's
frontend/andbackend/linked with[[links]]) get their own index; they shared one and re-indexed each other on every call. Such folders are indexed once more after updating. - Parsing threads get a larger stack, so very deeply nested files cannot crash a scan.