[{"data":1,"prerenderedAt":1294},["ShallowReactive",2],{"page-\u002Futils\u002Fguides\u002Fpermits":3,"navigation":912},{"collection":4,"page":5},"docs_en",{"id":6,"title":7,"body":8,"description":904,"extension":905,"meta":906,"navigation":99,"path":907,"rawbody":908,"seo":909,"stem":910,"__hash__":911},"docs_en\u002Futils\u002F2.guides\u002F3.permits.md","Permits",{"type":9,"value":10,"toc":897},"minimark",[11,32,44,49,201,207,320,334,337,375,379,399,649,685,697,701,801,805,853,869,873,893],[12,13,14,15,19,20,26,27,31],"p",{},"A ",[16,17,18],"code",{},"permits"," entry records an abstraction permit (outorga), an exemption or a registration: who issued it, its validity, the granted flow and volumes, and its conditions (condicionantes) with their fulfillments (",[21,22,24],"a",{"href":23},"\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#permits-since-v23",[16,25,18],{},"). The file stores the facts as written in the documents. Whether a permit is in force today, and which deadlines are due, is derived on the local calendar date at the well, never stored (",[21,28,30],{"href":29},"\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#permit-status-derived","permit status",").",[12,33,34,35,38,39,43],{},"The outputs on this page come from the ",[16,36,37],{},"colatina-es-gnaisse-rural"," ",[21,40,42],{"href":41},"\u002Fformat\u002Freference\u002Fexamples","example well",": an insignificant-use exemption from 2017, superseded in 2023 by an irrigation permit with a meter-installation condition and a yearly volume report.",[45,46,48],"h2",{"id":47},"status","Status",[50,51,56],"pre",{"className":52,"code":53,"language":54,"meta":55,"style":55},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { getPermitStatus } from '@welldot\u002Futils';\n\nfor (const permit of well.permits ?? []) {\n  console.log(permit.id, getPermitStatus(well, permit));\n}\n\u002F\u002F insig-2017    superseded\n\u002F\u002F outorga-2023  active\n","ts","",[16,57,58,94,101,138,182,188,195],{"__ignoreMap":55},[59,60,63,67,71,75,78,81,84,88,91],"span",{"class":61,"line":62},"line",1,[59,64,66],{"class":65},"s7zQu","import",[59,68,70],{"class":69},"sMK4o"," {",[59,72,74],{"class":73},"sTEyZ"," getPermitStatus",[59,76,77],{"class":69}," }",[59,79,80],{"class":65}," from",[59,82,83],{"class":69}," '",[59,85,87],{"class":86},"sfazB","@welldot\u002Futils",[59,89,90],{"class":69},"'",[59,92,93],{"class":69},";\n",[59,95,97],{"class":61,"line":96},2,[59,98,100],{"emptyLinePlaceholder":99},true,"\n",[59,102,104,107,110,114,117,120,123,126,129,132,135],{"class":61,"line":103},3,[59,105,106],{"class":65},"for",[59,108,109],{"class":73}," (",[59,111,113],{"class":112},"spNyl","const",[59,115,116],{"class":73}," permit ",[59,118,119],{"class":69},"of",[59,121,122],{"class":73}," well",[59,124,125],{"class":69},".",[59,127,128],{"class":73},"permits ",[59,130,131],{"class":69},"??",[59,133,134],{"class":73}," []) ",[59,136,137],{"class":69},"{\n",[59,139,141,144,146,150,154,157,159,162,165,167,169,172,174,177,180],{"class":61,"line":140},4,[59,142,143],{"class":73},"  console",[59,145,125],{"class":69},[59,147,149],{"class":148},"s2Zo4","log",[59,151,153],{"class":152},"swJcz","(",[59,155,156],{"class":73},"permit",[59,158,125],{"class":69},[59,160,161],{"class":73},"id",[59,163,164],{"class":69},",",[59,166,74],{"class":148},[59,168,153],{"class":152},[59,170,171],{"class":73},"well",[59,173,164],{"class":69},[59,175,176],{"class":73}," permit",[59,178,179],{"class":152},"))",[59,181,93],{"class":69},[59,183,185],{"class":61,"line":184},5,[59,186,187],{"class":69},"}\n",[59,189,191],{"class":61,"line":190},6,[59,192,194],{"class":193},"sHwdD","\u002F\u002F insig-2017    superseded\n",[59,196,198],{"class":61,"line":197},7,[59,199,200],{"class":193},"\u002F\u002F outorga-2023  active\n",[12,202,203,206],{},[16,204,205],{},"getPermitStatus(well, permit, today?)"," accepts a permit or its id and returns:",[208,209,210,222],"table",{},[211,212,213],"thead",{},[214,215,216,219],"tr",{},[217,218,48],"th",{},[217,220,221],{},"When",[223,224,225,256,270,284,294,308],"tbody",{},[214,226,227,246],{},[228,229,230,233,234,233,237,233,240,233,243],"td",{},[16,231,232],{},"requested",", ",[16,235,236],{},"suspended",[16,238,239],{},"revoked",[16,241,242],{},"denied",[16,244,245],{},"withdrawn",[228,247,248,249,251,252,31],{},"The stored administrative ",[16,250,47],{}," says so (",[21,253,255],{"href":254},"\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#administrative-status","administrative status",[214,257,258,263],{},[228,259,260],{},[16,261,262],{},"superseded",[228,264,265,266,269],{},"Another permit names this one in ",[16,267,268],{},"supersedes"," and has started.",[214,271,272,277],{},[228,273,274],{},[16,275,276],{},"not_yet_valid",[228,278,279,280,283],{},"Granted, but ",[16,281,282],{},"valid_from"," is in the future.",[214,285,286,291],{},[228,287,288],{},[16,289,290],{},"active",[228,292,293],{},"In force today.",[214,295,296,301],{},[228,297,298],{},[16,299,300],{},"active_pending_renewal",[228,302,303,304,307],{},"Past ",[16,305,306],{},"valid_until",", with a renewal requested in time.",[214,309,310,315],{},[228,311,312],{},[16,313,314],{},"expired",[228,316,303,317,319],{},[16,318,306],{},", with no renewal.",[12,321,322,325,326,329,330,333],{},[16,323,324],{},"today"," is a calendar date (",[16,327,328],{},"YYYY-MM-DD",") and defaults to today. Pass it explicitly in tests and reports, so the result does not change with the clock. ",[16,331,332],{},"PERMIT_STATUSES"," has English and Portuguese labels for each status.",[12,335,336],{},"Related helpers:",[338,339,340,347,355],"ul",{},[341,342,343,346],"li",{},[16,344,345],{},"getActivePermit(well, today?)",": the active permit with the latest start, the one production is checked against.",[341,348,349,352,353,125],{},[16,350,351],{},"getPermitEffectiveEnd(well, permit, today?)",": the day before the successor starts, else ",[16,354,306],{},[341,356,357,233,360,363,364,367,368,371,372,125],{},[16,358,359],{},"isPermitGranted(permit)",[16,361,362],{},"getPermitIdentifier(permit)"," (the ",[16,365,366],{},"identifier",", else the ",[16,369,370],{},"request_identifier","), ",[16,373,374],{},"permitLabel(permit)",[45,376,378],{"id":377},"condition-deadlines","Condition deadlines",[12,380,381,382,385,386,389,390,393,394,398],{},"A condition gives its deadline as a date, a duration after issue (",[16,383,384],{},"due_after: \"P90D\"",") or a recurrence (",[16,387,388],{},"first_due"," plus ",[16,391,392],{},"recurrence: \"P1Y\"","), in ISO 8601 durations (",[21,395,397],{"href":396},"\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#deadline-generation-normative","deadline generation","). The deadlines themselves are derived:",[50,400,402],{"className":52,"code":401,"language":54,"meta":55,"style":55},"import {\n  getConditionDeadlineStates,\n  getConditionDeadlines,\n} from '@welldot\u002Futils';\n\nconst permit = well.permits!.find(p => p.id === 'outorga-2023')!;\nconst reporting = permit.conditions!.find(c => c.id === 'c2')!; \u002F\u002F yearly volume report\n\ngetConditionDeadlines(well, permit, reporting);\n\u002F\u002F ['2024-01-31', '2025-01-31', '2026-01-31', …]\n\ngetConditionDeadlineStates(well, permit, reporting, { today: '2026-10-24' });\n\u002F\u002F [{ due_date: '2024-01-31', status: 'fulfilled', fulfillment_id: 'f-2024' },\n\u002F\u002F  { due_date: '2025-01-31', status: 'fulfilled', fulfillment_id: 'f-2025' },\n\u002F\u002F  { due_date: '2026-01-31', status: 'fulfilled', fulfillment_id: 'f-2026' },\n\u002F\u002F  { due_date: '2027-01-31', status: 'upcoming' }, …]\n",[16,403,404,411,419,426,441,445,498,549,554,574,580,585,625,631,637,643],{"__ignoreMap":55},[59,405,406,408],{"class":61,"line":62},[59,407,66],{"class":65},[59,409,410],{"class":69}," {\n",[59,412,413,416],{"class":61,"line":96},[59,414,415],{"class":73},"  getConditionDeadlineStates",[59,417,418],{"class":69},",\n",[59,420,421,424],{"class":61,"line":103},[59,422,423],{"class":73},"  getConditionDeadlines",[59,425,418],{"class":69},[59,427,428,431,433,435,437,439],{"class":61,"line":140},[59,429,430],{"class":69},"}",[59,432,80],{"class":65},[59,434,83],{"class":69},[59,436,87],{"class":86},[59,438,90],{"class":69},[59,440,93],{"class":69},[59,442,443],{"class":61,"line":184},[59,444,100],{"emptyLinePlaceholder":99},[59,446,447,449,451,454,456,458,460,463,466,468,471,474,477,479,482,485,487,490,492,495],{"class":61,"line":190},[59,448,113],{"class":112},[59,450,116],{"class":73},[59,452,453],{"class":69},"=",[59,455,122],{"class":73},[59,457,125],{"class":69},[59,459,18],{"class":73},[59,461,462],{"class":69},"!.",[59,464,465],{"class":148},"find",[59,467,153],{"class":73},[59,469,12],{"class":470},"sHdIc",[59,472,473],{"class":112}," =>",[59,475,476],{"class":73}," p",[59,478,125],{"class":69},[59,480,481],{"class":73},"id ",[59,483,484],{"class":69},"===",[59,486,83],{"class":69},[59,488,489],{"class":86},"outorga-2023",[59,491,90],{"class":69},[59,493,494],{"class":73},")",[59,496,497],{"class":69},"!;\n",[59,499,500,502,505,507,509,511,514,516,518,520,523,525,528,530,532,534,536,539,541,543,546],{"class":61,"line":197},[59,501,113],{"class":112},[59,503,504],{"class":73}," reporting ",[59,506,453],{"class":69},[59,508,176],{"class":73},[59,510,125],{"class":69},[59,512,513],{"class":73},"conditions",[59,515,462],{"class":69},[59,517,465],{"class":148},[59,519,153],{"class":73},[59,521,522],{"class":470},"c",[59,524,473],{"class":112},[59,526,527],{"class":73}," c",[59,529,125],{"class":69},[59,531,481],{"class":73},[59,533,484],{"class":69},[59,535,83],{"class":69},[59,537,538],{"class":86},"c2",[59,540,90],{"class":69},[59,542,494],{"class":73},[59,544,545],{"class":69},"!;",[59,547,548],{"class":193}," \u002F\u002F yearly volume report\n",[59,550,552],{"class":61,"line":551},8,[59,553,100],{"emptyLinePlaceholder":99},[59,555,557,560,563,565,567,569,572],{"class":61,"line":556},9,[59,558,559],{"class":148},"getConditionDeadlines",[59,561,562],{"class":73},"(well",[59,564,164],{"class":69},[59,566,176],{"class":73},[59,568,164],{"class":69},[59,570,571],{"class":73}," reporting)",[59,573,93],{"class":69},[59,575,577],{"class":61,"line":576},10,[59,578,579],{"class":193},"\u002F\u002F ['2024-01-31', '2025-01-31', '2026-01-31', …]\n",[59,581,583],{"class":61,"line":582},11,[59,584,100],{"emptyLinePlaceholder":99},[59,586,588,591,593,595,597,599,602,604,606,609,612,614,617,619,621,623],{"class":61,"line":587},12,[59,589,590],{"class":148},"getConditionDeadlineStates",[59,592,562],{"class":73},[59,594,164],{"class":69},[59,596,176],{"class":73},[59,598,164],{"class":69},[59,600,601],{"class":73}," reporting",[59,603,164],{"class":69},[59,605,70],{"class":69},[59,607,608],{"class":152}," today",[59,610,611],{"class":69},":",[59,613,83],{"class":69},[59,615,616],{"class":86},"2026-10-24",[59,618,90],{"class":69},[59,620,77],{"class":69},[59,622,494],{"class":73},[59,624,93],{"class":69},[59,626,628],{"class":61,"line":627},13,[59,629,630],{"class":193},"\u002F\u002F [{ due_date: '2024-01-31', status: 'fulfilled', fulfillment_id: 'f-2024' },\n",[59,632,634],{"class":61,"line":633},14,[59,635,636],{"class":193},"\u002F\u002F  { due_date: '2025-01-31', status: 'fulfilled', fulfillment_id: 'f-2025' },\n",[59,638,640],{"class":61,"line":639},15,[59,641,642],{"class":193},"\u002F\u002F  { due_date: '2026-01-31', status: 'fulfilled', fulfillment_id: 'f-2026' },\n",[59,644,646],{"class":61,"line":645},16,[59,647,648],{"class":193},"\u002F\u002F  { due_date: '2027-01-31', status: 'upcoming' }, …]\n",[12,650,651,652,233,655,233,658,661,662,665,666,669,670,109,673,677,678,661,681,684],{},"Each state is ",[16,653,654],{},"fulfilled",[16,656,657],{},"fulfilled_late",[16,659,660],{},"upcoming"," or ",[16,663,664],{},"overdue",", matched against the condition's ",[16,667,668],{},"fulfillments"," by ",[16,671,672],{},"due_date",[21,674,676],{"href":675},"\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#condition-fulfillment","condition fulfillment","). Deadlines stop at the condition's ",[16,679,680],{},"occurrences",[16,682,683],{},"last_due",", at the permit's effective end or at a horizon; a permit that was never granted has none.",[12,686,687,688,233,691,233,694,125],{},"Month-end dates are clamped (a monthly deadline from 31 January falls on 28 or 29 February). The duration helpers are exported too: ",[16,689,690],{},"parseDateDuration",[16,692,693],{},"addDateDuration",[16,695,696],{},"todayCalendarDate",[45,698,700],{"id":699},"history-and-timeline","History and timeline",[50,702,704],{"className":52,"code":703,"language":54,"meta":55,"style":55},"import {\n  getOverduePermitHistory,\n  getPermitHistory,\n  getPermitTimeline,\n} from '@welldot\u002Futils';\n\ngetPermitHistory(permit); \u002F\u002F administrative steps sorted by date\ngetOverduePermitHistory(permit); \u002F\u002F steps past due_date and not done\ngetPermitTimeline(permit, 'America\u002FSao_Paulo'); \u002F\u002F steps and fulfillments, newest first\n",[16,705,706,712,719,726,733,747,751,765,777],{"__ignoreMap":55},[59,707,708,710],{"class":61,"line":62},[59,709,66],{"class":65},[59,711,410],{"class":69},[59,713,714,717],{"class":61,"line":96},[59,715,716],{"class":73},"  getOverduePermitHistory",[59,718,418],{"class":69},[59,720,721,724],{"class":61,"line":103},[59,722,723],{"class":73},"  getPermitHistory",[59,725,418],{"class":69},[59,727,728,731],{"class":61,"line":140},[59,729,730],{"class":73},"  getPermitTimeline",[59,732,418],{"class":69},[59,734,735,737,739,741,743,745],{"class":61,"line":184},[59,736,430],{"class":69},[59,738,80],{"class":65},[59,740,83],{"class":69},[59,742,87],{"class":86},[59,744,90],{"class":69},[59,746,93],{"class":69},[59,748,749],{"class":61,"line":190},[59,750,100],{"emptyLinePlaceholder":99},[59,752,753,756,759,762],{"class":61,"line":197},[59,754,755],{"class":148},"getPermitHistory",[59,757,758],{"class":73},"(permit)",[59,760,761],{"class":69},";",[59,763,764],{"class":193}," \u002F\u002F administrative steps sorted by date\n",[59,766,767,770,772,774],{"class":61,"line":551},[59,768,769],{"class":148},"getOverduePermitHistory",[59,771,758],{"class":73},[59,773,761],{"class":69},[59,775,776],{"class":193}," \u002F\u002F steps past due_date and not done\n",[59,778,779,782,785,787,789,792,794,796,798],{"class":61,"line":556},[59,780,781],{"class":148},"getPermitTimeline",[59,783,784],{"class":73},"(permit",[59,786,164],{"class":69},[59,788,83],{"class":69},[59,790,791],{"class":86},"America\u002FSao_Paulo",[59,793,90],{"class":69},[59,795,494],{"class":73},[59,797,761],{"class":69},[59,799,800],{"class":193}," \u002F\u002F steps and fulfillments, newest first\n",[45,802,804],{"id":803},"warnings","Warnings",[50,806,808],{"className":52,"code":807,"language":54,"meta":55,"style":55},"import { getPermitWarnings } from '@welldot\u002Futils';\n\ngetPermitWarnings(well); \u002F\u002F [] for a consistent file\n\u002F\u002F [{ code: 'missing_timezone', ids: ['outorga-2023'] }] once location.properties.timezone is removed\n",[16,809,810,831,835,848],{"__ignoreMap":55},[59,811,812,814,816,819,821,823,825,827,829],{"class":61,"line":62},[59,813,66],{"class":65},[59,815,70],{"class":69},[59,817,818],{"class":73}," getPermitWarnings",[59,820,77],{"class":69},[59,822,80],{"class":65},[59,824,83],{"class":69},[59,826,87],{"class":86},[59,828,90],{"class":69},[59,830,93],{"class":69},[59,832,833],{"class":61,"line":96},[59,834,100],{"emptyLinePlaceholder":99},[59,836,837,840,843,845],{"class":61,"line":103},[59,838,839],{"class":148},"getPermitWarnings",[59,841,842],{"class":73},"(well)",[59,844,761],{"class":69},[59,846,847],{"class":193}," \u002F\u002F [] for a consistent file\n",[59,849,850],{"class":61,"line":140},[59,851,852],{"class":193},"\u002F\u002F [{ code: 'missing_timezone', ids: ['outorga-2023'] }] once location.properties.timezone is removed\n",[12,854,855,856,858,859,863,864,868],{},"Permit warnings point at data that is valid but inconsistent: validity in the wrong order, a broken ",[16,857,268],{}," chain, overlapping permits, a daily operating time above 24 h (read as 24), monthly maxima above the annual limit, duplicates, missing identifiers, fulfillments that match no deadline, and, since 2.4, a missing site time zone when conditions have fulfillments. None of them makes a file invalid (",[21,860,862],{"href":861},"\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#validation-warnings-never-rejection-1","permit validation","). The ",[21,865,867],{"href":866},"\u002Fai\u002Fmcp","docs MCP server"," returns them alongside the validation result.",[45,870,872],{"id":871},"time-zone","Time zone",[12,874,875,876,879,880,884,885,888,889,892],{},"Local dates are computed in ",[16,877,878],{},"location.properties.timezone"," when the file has one, otherwise from the offset written in each instant (",[21,881,883],{"href":882},"\u002Fformat\u002Fspec\u002Fv2\u002Fformat-reference#datetime-conventions","datetime conventions","). ",[16,886,887],{},"getWellTimeZone(well)"," returns the zone and ",[16,890,891],{},"instantLocalDate(instant, timeZone?)"," converts an instant to its local date.",[894,895,896],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":55,"searchDepth":96,"depth":96,"links":898},[899,900,901,902,903],{"id":47,"depth":96,"text":48},{"id":377,"depth":96,"text":378},{"id":699,"depth":96,"text":700},{"id":803,"depth":96,"text":804},{"id":871,"depth":96,"text":872},"Derive a permit's status, list condition deadlines and whether each was met, follow renewals, and collect permit warnings with @welldot\u002Futils.","md",{},"\u002Futils\u002Fguides\u002Fpermits","---\ntitle: Permits\ndescription: Derive a permit's status, list condition deadlines and whether each was met, follow renewals, and collect permit warnings with @welldot\u002Futils.\n---\n\nA `permits` entry records an abstraction permit (outorga), an exemption or a registration: who issued it, its validity, the granted flow and volumes, and its conditions (condicionantes) with their fulfillments ([`permits`](\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#permits-since-v23)). The file stores the facts as written in the documents. Whether a permit is in force today, and which deadlines are due, is derived on the local calendar date at the well, never stored ([permit status](\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#permit-status-derived)).\n\nThe outputs on this page come from the `colatina-es-gnaisse-rural` [example well](\u002Fformat\u002Freference\u002Fexamples): an insignificant-use exemption from 2017, superseded in 2023 by an irrigation permit with a meter-installation condition and a yearly volume report.\n\n## Status\n\n```ts\nimport { getPermitStatus } from '@welldot\u002Futils';\n\nfor (const permit of well.permits ?? []) {\n  console.log(permit.id, getPermitStatus(well, permit));\n}\n\u002F\u002F insig-2017    superseded\n\u002F\u002F outorga-2023  active\n```\n\n`getPermitStatus(well, permit, today?)` accepts a permit or its id and returns:\n\n| Status                                                     | When                                                                                                                        |\n| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |\n| `requested`, `suspended`, `revoked`, `denied`, `withdrawn` | The stored administrative `status` says so ([administrative status](\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#administrative-status)). |\n| `superseded`                                               | Another permit names this one in `supersedes` and has started.                                                              |\n| `not_yet_valid`                                            | Granted, but `valid_from` is in the future.                                                                                 |\n| `active`                                                   | In force today.                                                                                                             |\n| `active_pending_renewal`                                   | Past `valid_until`, with a renewal requested in time.                                                                       |\n| `expired`                                                  | Past `valid_until`, with no renewal.                                                                                        |\n\n`today` is a calendar date (`YYYY-MM-DD`) and defaults to today. Pass it explicitly in tests and reports, so the result does not change with the clock. `PERMIT_STATUSES` has English and Portuguese labels for each status.\n\nRelated helpers:\n\n- `getActivePermit(well, today?)`: the active permit with the latest start, the one production is checked against.\n- `getPermitEffectiveEnd(well, permit, today?)`: the day before the successor starts, else `valid_until`.\n- `isPermitGranted(permit)`, `getPermitIdentifier(permit)` (the `identifier`, else the `request_identifier`), `permitLabel(permit)`.\n\n## Condition deadlines\n\nA condition gives its deadline as a date, a duration after issue (`due_after: \"P90D\"`) or a recurrence (`first_due` plus `recurrence: \"P1Y\"`), in ISO 8601 durations ([deadline generation](\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#deadline-generation-normative)). The deadlines themselves are derived:\n\n```ts\nimport {\n  getConditionDeadlineStates,\n  getConditionDeadlines,\n} from '@welldot\u002Futils';\n\nconst permit = well.permits!.find(p => p.id === 'outorga-2023')!;\nconst reporting = permit.conditions!.find(c => c.id === 'c2')!; \u002F\u002F yearly volume report\n\ngetConditionDeadlines(well, permit, reporting);\n\u002F\u002F ['2024-01-31', '2025-01-31', '2026-01-31', …]\n\ngetConditionDeadlineStates(well, permit, reporting, { today: '2026-10-24' });\n\u002F\u002F [{ due_date: '2024-01-31', status: 'fulfilled', fulfillment_id: 'f-2024' },\n\u002F\u002F  { due_date: '2025-01-31', status: 'fulfilled', fulfillment_id: 'f-2025' },\n\u002F\u002F  { due_date: '2026-01-31', status: 'fulfilled', fulfillment_id: 'f-2026' },\n\u002F\u002F  { due_date: '2027-01-31', status: 'upcoming' }, …]\n```\n\nEach state is `fulfilled`, `fulfilled_late`, `upcoming` or `overdue`, matched against the condition's `fulfillments` by `due_date` ([condition fulfillment](\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#condition-fulfillment)). Deadlines stop at the condition's `occurrences` or `last_due`, at the permit's effective end or at a horizon; a permit that was never granted has none.\n\nMonth-end dates are clamped (a monthly deadline from 31 January falls on 28 or 29 February). The duration helpers are exported too: `parseDateDuration`, `addDateDuration`, `todayCalendarDate`.\n\n## History and timeline\n\n```ts\nimport {\n  getOverduePermitHistory,\n  getPermitHistory,\n  getPermitTimeline,\n} from '@welldot\u002Futils';\n\ngetPermitHistory(permit); \u002F\u002F administrative steps sorted by date\ngetOverduePermitHistory(permit); \u002F\u002F steps past due_date and not done\ngetPermitTimeline(permit, 'America\u002FSao_Paulo'); \u002F\u002F steps and fulfillments, newest first\n```\n\n## Warnings\n\n```ts\nimport { getPermitWarnings } from '@welldot\u002Futils';\n\ngetPermitWarnings(well); \u002F\u002F [] for a consistent file\n\u002F\u002F [{ code: 'missing_timezone', ids: ['outorga-2023'] }] once location.properties.timezone is removed\n```\n\nPermit warnings point at data that is valid but inconsistent: validity in the wrong order, a broken `supersedes` chain, overlapping permits, a daily operating time above 24 h (read as 24), monthly maxima above the annual limit, duplicates, missing identifiers, fulfillments that match no deadline, and, since 2.4, a missing site time zone when conditions have fulfillments. None of them makes a file invalid ([permit validation](\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas#validation-warnings-never-rejection-1)). The [docs MCP server](\u002Fai\u002Fmcp) returns them alongside the validation result.\n\n## Time zone\n\nLocal dates are computed in `location.properties.timezone` when the file has one, otherwise from the offset written in each instant ([datetime conventions](\u002Fformat\u002Fspec\u002Fv2\u002Fformat-reference#datetime-conventions)). `getWellTimeZone(well)` returns the zone and `instantLocalDate(instant, timeZone?)` converts an instant to its local date.\n",{"title":7,"description":904},"utils\u002F2.guides\u002F3.permits","Xtr8LXCTQakL_ZyecK6dwWnSWOK-svgYiLnFj_u9AAU",{"docs_en":913,"spec":1226,"changelogs":1276},[914,933,952,1008,1117,1171],{"title":915,"path":916,"stem":917,"children":918},"Ai","\u002Fai","ai",[919,922,926,930],{"title":920,"path":916,"stem":921},"Introduction","ai\u002Findex",{"title":923,"path":924,"stem":925},"Converting reports with an assistant","\u002Fai\u002Fconversion-skill","ai\u002Fconversion-skill",{"title":927,"path":928,"stem":929},"llms.txt and Markdown pages","\u002Fai\u002Fllms","ai\u002Fllms",{"title":931,"path":866,"stem":932},"MCP server","ai\u002Fmcp",{"title":934,"path":935,"stem":936,"children":937},"Contributing","\u002Fcontributing","contributing",[938,940,944,948],{"title":920,"path":935,"stem":939},"contributing\u002Findex",{"title":941,"path":942,"stem":943},"Writing docs","\u002Fcontributing\u002Fwriting-docs","contributing\u002F1.writing-docs",{"title":945,"path":946,"stem":947},"Update rules","\u002Fcontributing\u002Fupdate-rules","contributing\u002F2.update-rules",{"title":949,"path":950,"stem":951},"Content components","\u002Fcontributing\u002Fcomponents","contributing\u002Fcomponents",{"title":953,"path":954,"stem":955,"children":956},"Core","\u002Fcore","core",[957,959,973,1002],{"title":920,"path":954,"stem":958},"core\u002Findex",{"title":960,"path":961,"stem":962,"children":963,"page":972},"Getting Started","\u002Fcore\u002Fgetting-started","core\u002F1.getting-started",[964,968],{"title":965,"path":966,"stem":967},"Installation","\u002Fcore\u002Fgetting-started\u002Finstallation","core\u002F1.getting-started\u002F1.installation",{"title":969,"path":970,"stem":971},"First use","\u002Fcore\u002Fgetting-started\u002Ffirst-use","core\u002F1.getting-started\u002F2.first-use",false,{"title":974,"path":975,"stem":976,"children":977,"page":972},"Guides","\u002Fcore\u002Fguides","core\u002F2.guides",[978,982,986,990,994,998],{"title":979,"path":980,"stem":981},"Parsing and validating","\u002Fcore\u002Fguides\u002Fparsing-and-validating","core\u002F2.guides\u002F1.parsing-and-validating",{"title":983,"path":984,"stem":985},"Serializing and sharing","\u002Fcore\u002Fguides\u002Fserializing-and-sharing","core\u002F2.guides\u002F2.serializing-and-sharing",{"title":987,"path":988,"stem":989},"Unit conversion","\u002Fcore\u002Fguides\u002Funit-conversion","core\u002F2.guides\u002F3.unit-conversion",{"title":991,"path":992,"stem":993},"Vocabularies and textures","\u002Fcore\u002Fguides\u002Fvocabularies-and-textures","core\u002F2.guides\u002F4.vocabularies-and-textures",{"title":995,"path":996,"stem":997},"Water quality vocabulary","\u002Fcore\u002Fguides\u002Fwater-quality-vocabulary","core\u002F2.guides\u002F5.water-quality-vocabulary",{"title":999,"path":1000,"stem":1001},"Versions and time zones","\u002Fcore\u002Fguides\u002Fversions-and-time-zones","core\u002F2.guides\u002F6.versions-and-time-zones",{"title":1003,"path":1004,"stem":1005,"children":1006},"API reference","\u002Fcore\u002Fapi","core\u002Fapi\u002Findex",[1007],{"title":1003,"path":1004,"stem":1005},{"title":1009,"path":1010,"stem":1011,"children":1012},"Format","\u002Fformat","format",[1013,1015,1035,1064,1088,1107,1113],{"title":920,"path":1010,"stem":1014},"format\u002Findex",{"title":960,"path":1016,"stem":1017,"children":1018,"page":972},"\u002Fformat\u002Fgetting-started","format\u002F1.getting-started",[1019,1023,1027,1031],{"title":1020,"path":1021,"stem":1022},"What is .well?","\u002Fformat\u002Fgetting-started\u002Fwhat-is-well","format\u002F1.getting-started\u002F1.what-is-well",{"title":1024,"path":1025,"stem":1026},"For geologists","\u002Fformat\u002Fgetting-started\u002Ffor-geologists","format\u002F1.getting-started\u002F2.for-geologists",{"title":1028,"path":1029,"stem":1030},"For developers","\u002Fformat\u002Fgetting-started\u002Ffor-developers","format\u002F1.getting-started\u002F3.for-developers",{"title":1032,"path":1033,"stem":1034},"Your first .well file","\u002Fformat\u002Fgetting-started\u002Ffirst-well-file","format\u002F1.getting-started\u002F4.first-well-file",{"title":1036,"path":1037,"stem":1038,"children":1039,"page":972},"Concepts","\u002Fformat\u002Fconcepts","format\u002F2.concepts",[1040,1044,1048,1052,1056,1060],{"title":1041,"path":1042,"stem":1043},"Depths and intervals","\u002Fformat\u002Fconcepts\u002Fdepths-and-intervals","format\u002F2.concepts\u002F1.depths-and-intervals",{"title":1045,"path":1046,"stem":1047},"Units and precision","\u002Fformat\u002Fconcepts\u002Funits-and-precision","format\u002F2.concepts\u002F2.units-and-precision",{"title":1049,"path":1050,"stem":1051},"Vocabularies","\u002Fformat\u002Fconcepts\u002Fvocabularies","format\u002F2.concepts\u002F3.vocabularies",{"title":1053,"path":1054,"stem":1055},"Profiles","\u002Fformat\u002Fconcepts\u002Fprofiles","format\u002F2.concepts\u002F4.profiles",{"title":1057,"path":1058,"stem":1059},"Versions and deprecation","\u002Fformat\u002Fconcepts\u002Fversions-and-deprecation","format\u002F2.concepts\u002F5.versions-and-deprecation",{"title":1061,"path":1062,"stem":1063},"Extensibility","\u002Fformat\u002Fconcepts\u002Fextensibility","format\u002F2.concepts\u002F6.extensibility",{"title":974,"path":1065,"stem":1066,"children":1067,"page":972},"\u002Fformat\u002Fguides","format\u002F3.guides",[1068,1072,1076,1080,1084],{"title":1069,"path":1070,"stem":1071},"Writing a .well by hand","\u002Fformat\u002Fguides\u002Fwriting-by-hand","format\u002F3.guides\u002F1.writing-by-hand",{"title":1073,"path":1074,"stem":1075},"Converting a report","\u002Fformat\u002Fguides\u002Fconverting-a-report","format\u002F3.guides\u002F2.converting-a-report",{"title":1077,"path":1078,"stem":1079},"Validating","\u002Fformat\u002Fguides\u002Fvalidating","format\u002F3.guides\u002F3.validating",{"title":1081,"path":1082,"stem":1083},"Extending for your own needs","\u002Fformat\u002Fguides\u002Fextending","format\u002F3.guides\u002F4.extending",{"title":1085,"path":1086,"stem":1087},"Building an editor or database on .well","\u002Fformat\u002Fguides\u002Fbuilding-on-well","format\u002F3.guides\u002F5.building-on-well",{"title":1089,"path":1090,"stem":1091,"children":1092},"Overview","\u002Fformat\u002Freference","format\u002F4.reference\u002Findex",[1093,1094,1098,1101],{"title":1089,"path":1090,"stem":1091},{"title":1095,"path":1096,"stem":1097},"JSON Schema","\u002Fformat\u002Freference\u002Fjson-schema","format\u002F4.reference\u002F1.json-schema",{"title":1099,"path":41,"stem":1100},"Example wells","format\u002F4.reference\u002F2.examples",{"title":1102,"path":1103,"stem":1104,"children":1105},"Object reference","\u002Fformat\u002Freference\u002Fobjects","format\u002Freference\u002Fobjects\u002Findex",[1106],{"title":1102,"path":1103,"stem":1104},{"title":1108,"path":1109,"stem":1110,"children":1111},"About the spec","\u002Fformat\u002Fspec","format\u002F5.spec\u002Findex",[1112],{"title":1108,"path":1109,"stem":1110},{"title":1114,"path":1115,"stem":1116},"Changelog","\u002Fformat\u002Fchangelog","format\u002F6.changelog",{"title":1118,"path":1119,"stem":1120,"children":1121},"Render","\u002Frender","render",[1122,1124,1134,1166],{"title":920,"path":1119,"stem":1123},"render\u002Findex",{"title":960,"path":1125,"stem":1126,"children":1127,"page":972},"\u002Frender\u002Fgetting-started","render\u002F1.getting-started",[1128,1131],{"title":965,"path":1129,"stem":1130},"\u002Frender\u002Fgetting-started\u002Finstallation","render\u002F1.getting-started\u002F1.installation",{"title":969,"path":1132,"stem":1133},"\u002Frender\u002Fgetting-started\u002Ffirst-use","render\u002F1.getting-started\u002F2.first-use",{"title":974,"path":1135,"stem":1136,"children":1137,"page":972},"\u002Frender\u002Fguides","render\u002F2.guides",[1138,1142,1146,1150,1154,1158,1162],{"title":1139,"path":1140,"stem":1141},"Panels and layout","\u002Frender\u002Fguides\u002Fpanels-and-layout","render\u002F2.guides\u002F1.panels-and-layout",{"title":1143,"path":1144,"stem":1145},"Layers and labels","\u002Frender\u002Fguides\u002Flayers-and-labels","render\u002F2.guides\u002F2.layers-and-labels",{"title":1147,"path":1148,"stem":1149},"Theming","\u002Frender\u002Fguides\u002Ftheming","render\u002F2.guides\u002F3.theming",{"title":1151,"path":1152,"stem":1153},"Locale and units","\u002Frender\u002Fguides\u002Flocale-and-units","render\u002F2.guides\u002F4.locale-and-units",{"title":1155,"path":1156,"stem":1157},"Legends","\u002Frender\u002Fguides\u002Flegends","render\u002F2.guides\u002F5.legends",{"title":1159,"path":1160,"stem":1161},"Zoom, pan and highlights","\u002Frender\u002Fguides\u002Finteraction","render\u002F2.guides\u002F6.interaction",{"title":1163,"path":1164,"stem":1165},"Using it in a framework","\u002Frender\u002Fguides\u002Fframeworks","render\u002F2.guides\u002F7.frameworks",{"title":1003,"path":1167,"stem":1168,"children":1169},"\u002Frender\u002Fapi","render\u002Fapi\u002Findex",[1170],{"title":1003,"path":1167,"stem":1168},{"title":1172,"path":1173,"stem":1174,"children":1175},"Utils","\u002Futils","utils",[1176,1178,1188,1221],{"title":920,"path":1173,"stem":1177},"utils\u002Findex",{"title":960,"path":1179,"stem":1180,"children":1181,"page":972},"\u002Futils\u002Fgetting-started","utils\u002F1.getting-started",[1182,1185],{"title":965,"path":1183,"stem":1184},"\u002Futils\u002Fgetting-started\u002Finstallation","utils\u002F1.getting-started\u002F1.installation",{"title":969,"path":1186,"stem":1187},"\u002Futils\u002Fgetting-started\u002Ffirst-use","utils\u002F1.getting-started\u002F2.first-use",{"title":974,"path":1189,"stem":1190,"children":1191,"page":972},"\u002Futils\u002Fguides","utils\u002F2.guides",[1192,1196,1200,1201,1205,1209,1213,1217],{"title":1193,"path":1194,"stem":1195},"Geometry and volumes","\u002Futils\u002Fguides\u002Fgeometry-and-volumes","utils\u002F2.guides\u002F1.geometry-and-volumes",{"title":1197,"path":1198,"stem":1199},"Water levels and pumping tests","\u002Futils\u002Fguides\u002Fpumping-tests","utils\u002F2.guides\u002F2.pumping-tests",{"title":7,"path":907,"stem":910},{"title":1202,"path":1203,"stem":1204},"Operation and production","\u002Futils\u002Fguides\u002Foperation","utils\u002F2.guides\u002F4.operation",{"title":1206,"path":1207,"stem":1208},"Water quality","\u002Futils\u002Fguides\u002Fwater-quality","utils\u002F2.guides\u002F5.water-quality",{"title":1210,"path":1211,"stem":1212},"Logger import","\u002Futils\u002Fguides\u002Flogger-import","utils\u002F2.guides\u002F6.logger-import",{"title":1214,"path":1215,"stem":1216},"SIAGAS import","\u002Futils\u002Fguides\u002Fsiagas-import","utils\u002F2.guides\u002F7.siagas-import",{"title":1218,"path":1219,"stem":1220},"Formatting","\u002Futils\u002Fguides\u002Fformatting","utils\u002F2.guides\u002F8.formatting",{"title":1003,"path":1222,"stem":1223,"children":1224},"\u002Futils\u002Fapi","utils\u002Fapi\u002Findex",[1225],{"title":1003,"path":1222,"stem":1223},[1227],{"title":1009,"path":1010,"stem":1011,"children":1228,"page":972},[1229],{"title":1230,"path":1109,"stem":1231,"children":1232,"page":972},"Spec","format\u002Fspec",[1233,1242,1251],{"title":1234,"path":1235,"stem":1236,"children":1237,"page":972},"Reference","\u002Fformat\u002Fspec\u002Freference","format\u002Fspec\u002Freference",[1238],{"title":1239,"path":1240,"stem":1241},"FGDC Texture Patterns Reference","\u002Fformat\u002Fspec\u002Freference\u002Ffgdc-textures","format\u002Fspec\u002Freference\u002Ffgdc-textures",{"title":1243,"path":1244,"stem":1245,"children":1246,"page":972},"V1","\u002Fformat\u002Fspec\u002Fv1","format\u002Fspec\u002Fv1",[1247],{"title":1248,"path":1249,"stem":1250},".well File Format Specification","\u002Fformat\u002Fspec\u002Fv1\u002Fwell-format","format\u002Fspec\u002Fv1\u002Fwell-format",{"title":1252,"path":1253,"stem":1254,"children":1255,"page":972},"V2","\u002Fformat\u002Fspec\u002Fv2","format\u002Fspec\u002Fv2",[1256,1260,1264,1268,1272],{"title":1257,"path":1258,"stem":1259},".well File Format Specification — Version 2.4: Format Reference","\u002Fformat\u002Fspec\u002Fv2\u002Fformat-reference","format\u002Fspec\u002Fv2\u002Fformat-reference",{"title":1261,"path":1262,"stem":1263},".well File Format Specification — Version 2.4: Interoperability","\u002Fformat\u002Fspec\u002Fv2\u002Finteroperability","format\u002Fspec\u002Fv2\u002Finteroperability",{"title":1265,"path":1266,"stem":1267},".well File Format Specification — Version 2.4: Object Schemas","\u002Fformat\u002Fspec\u002Fv2\u002Fobject-schemas","format\u002Fspec\u002Fv2\u002Fobject-schemas",{"title":1269,"path":1270,"stem":1271},".well File Format Specification — Version 2.4: Overview","\u002Fformat\u002Fspec\u002Fv2\u002Foverview","format\u002Fspec\u002Fv2\u002Foverview",{"title":1273,"path":1274,"stem":1275},".well File Format Specification — Version 2.4: Water Quality","\u002Fformat\u002Fspec\u002Fv2\u002Fwater-quality","format\u002Fspec\u002Fv2\u002Fwater-quality",[1277,1283,1289],{"title":953,"path":954,"stem":955,"children":1278,"page":972},[1279],{"title":1280,"path":1281,"stem":1282},"@welldot\u002Fcore","\u002Fcore\u002Fchangelog","core\u002FCHANGELOG",{"title":1118,"path":1119,"stem":1120,"children":1284,"page":972},[1285],{"title":1286,"path":1287,"stem":1288},"@welldot\u002Frender","\u002Frender\u002Fchangelog","render\u002FCHANGELOG",{"title":1172,"path":1173,"stem":1174,"children":1290,"page":972},[1291],{"title":87,"path":1292,"stem":1293},"\u002Futils\u002Fchangelog","utils\u002FCHANGELOG",1793050495414]