001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.server;
018
019import static java.lang.annotation.ElementType.*;
020import static java.lang.annotation.RetentionPolicy.*;
021
022import java.lang.annotation.*;
023
024/**
025 * Declares that a REST operation changes state, so that binding it to an HTTP method defined as safe becomes a
026 * startup failure instead of a silent mistake.
027 *
028 * <h5 class='section'>The mistake this exists to catch</h5>
029 * <p>
030 * RFC 9110 defines {@code GET}, {@code HEAD}, {@code OPTIONS} and {@code TRACE} as <i>safe</i>: a client, a proxy,
031 * a crawler or a browser prefetcher may issue them freely, repeat them, and follow them without asking, precisely
032 * because they are defined not to change anything.  Everything downstream of a request is built on that promise
033 * &mdash; caches store the response, link prefetchers fire the request before the user clicks, and every CSRF
034 * defence in existence, including {@link org.apache.juneau.rest.server.filter.LoopbackBoundary}, applies its checks
035 * only to the methods that are <i>not</i> safe.
036 * <p>
037 * So a handler that mutates state behind {@code GET} does not merely misuse a verb.  It sits behind whichever of
038 * those checks the application relies on, having quietly opted out of all of them &mdash; not by disabling
039 * anything, but by being classified as harmless.  Nothing about it looks wrong at the call site, and nothing
040 * reports it at runtime, because from the boundary's point of view a {@code GET} arriving without a CSRF token is
041 * an ordinary read.
042 * <p>
043 * That is the failure mode this annotation exists to convert into a boot error:
044 * <p class='bjava'>
045 *    <jc>// Fails at startup: this mutates, and @RestOp with no method= and a name that starts with none of
046 *    // get/put/post/delete resolves to GET.</jc>
047 *    <ja>@Mutating</ja>
048 *    <ja>@RestOp</ja>
049 *    <jk>public</jk> Result <jsm>armRelease</jsm>(...) {...}
050 * </p>
051 * <p>
052 * The {@code @RestOp} case above is worth singling out, because the developer never typed {@code GET} anywhere:
053 * with no {@code method=} and a Java method name whose prefix is not one of {@code get}/{@code put}/{@code post}/
054 * {@code delete}, the resolved method <b>defaults to {@code GET}</b>.  A mutating operation therefore lands on a
055 * safe method through nobody's decision.  The check resolves the method the same way dispatch does, so it sees the
056 * inferred {@code GET} rather than the absent annotation.
057 *
058 * <h5 class='section'>Why this is declared and not detected</h5>
059 * <p>
060 * The obvious alternative is for the framework to work out for itself which handlers mutate, and it was rejected
061 * because no sound version of it exists.  "Mutates" is a claim about effects on state the <i>application</i> cares
062 * about, and that has no syntactic signature:
063 * <p class='bjava'>
064 *    <jv>runner</jv>.run(List.<jsm>of</jsm>(<js>"svn"</js>, <js>"commit"</js>, <jv>path</jv>));  <jc>// mutates the world</jc>
065 *    <jv>runner</jv>.run(List.<jsm>of</jsm>(<js>"svn"</js>, <js>"info"</js>, <jv>path</jv>));    <jc>// mutates nothing</jc>
066 * </p>
067 * <p>
068 * Those are the same call to the same method with the same argument type, and telling them apart requires knowing
069 * what {@code svn} does.  No analysis of the Java program can supply that.  Any analysis strong enough to see
070 * through the indirection real applications use &mdash; an interface for the process runner, a supplier for the
071 * credential, a method reference for the callback, an HTTP client whose URL is chosen at runtime &mdash; is a
072 * whole-program points-to analysis, and it would still be wrong on the two lines above.
073 * <p>
074 * A naming heuristic ({@code set*}, {@code save*}, {@code delete*}) fails in both directions
075 * &mdash; {@code getOrCreateSession} mutates, {@code applyFilter} does not &mdash; and has a worse property than
076 * being unreliable: it would make renaming a Java method change the application's security posture.
077 * <p>
078 * Inspecting the signature fares no better.  A mutating operation need take nothing but a {@code @Path}: deleting
079 * a record by id, or validating a stored credential and caching the verdict, both mutate while taking no body at
080 * all.
081 * <p>
082 * The decisive argument is about the cost of being wrong.  This check's failure mode is <b>the application does
083 * not start</b>.  A check that can refuse to start an application it merely suspects will be switched off, and a
084 * check that has been switched off protects nothing &mdash; including against the real contradictions it would
085 * have caught.  So the rule here is one a machine can evaluate with certainty: the developer stated that this
086 * operation mutates, and the operation is bound to a method defined as safe.  Those cannot both be intended, and
087 * no inference is involved in noticing it.
088 *
089 * <h5 class='section'>What this does not catch</h5>
090 * <p>
091 * <b>An operation that mutates and says nothing is invisible to this check.</b>  The check finds contradictions,
092 * not omissions, and a developer who does not reach for the annotation gets no protection from it.  That limit is
093 * inherent in the previous section: the alternative to a declaration that can be forgotten is an inference that
094 * can be wrong, and at a gate that stops the application from booting, wrong is worse.
095 * <p>
096 * What makes the limit acceptable is that the annotation is <b>strictly additive</b>.  It can only ever cause a
097 * boot failure; it never relaxes a runtime check.  Its opposite, {@link RestOp#read() @RestOp(read=true)}, is
098 * accepted only on custom methods and cannot declare a {@code POST}, {@code PUT}, {@code PATCH} or {@code DELETE}
099 * safe.  An operation that omits it is therefore treated exactly as it would be if this
100 * annotation did not exist &mdash; the boundary still classifies by HTTP method, still treats an unknown method as
101 * state-changing, and still applies every write check to every non-safe method.  Adopting the annotation can move
102 * an application from "wrong and silent" to "refuses to start"; it cannot move one from "protected" to
103 * "unprotected".
104 * <p>
105 * For the same reason this is <b>method-level only</b>.  A class-level form meaning "everything here mutates"
106 * would be convenient and would immediately produce false failures on the page-rendering {@code GET} that nearly
107 * every such resource also has &mdash; reintroducing exactly the false-positive problem that ruled out inference.
108 *
109 * <h5 class='section'>When it runs</h5>
110 * <p>
111 * When the resource's operation table is assembled: at startup under {@link Rest#eagerInit()}, and otherwise on
112 * the first request to that resource.  In both cases it runs <b>before any operation on that resource can be
113 * dispatched</b>, so a contradiction cannot be reached by a request.  An application wanting the failure at boot
114 * literally should set {@code eagerInit}.
115 * <p>
116 * The check is unconditional and needs no wiring.  It is not part of any filter, because HTTP method safety is not
117 * a property of a security filter &mdash; it is a property of the resource, which the filter then depends on.  An
118 * application with no {@code @Mutating} anywhere is unaffected.
119 *
120 * <h5 class='section'>Example:</h5>
121 * <p class='bjava'>
122 *    <jc>// Correct: declared mutating, bound to a method that is not safe.  Boots, and the boundary's write
123 *    // checks apply to it because POST is not in the safe set.</jc>
124 *    <ja>@Mutating</ja>
125 *    <ja>@RestPost</ja>(<js>"/{version}/arm"</js>)
126 *    <jk>public</jk> ArmResult <jsm>arm</jsm>(<ja>@Path</ja>(<js>"version"</js>) String <jv>version</jv>, <ja>@Content</ja> ArmRequest <jv>body</jv>) {...}
127 * </p>
128 *
129 * <h5 class='section'>See Also:</h5><ul>
130 *    <li class='jc'>{@link org.apache.juneau.rest.server.filter.LoopbackBoundary}
131 *    <li class='jm'>{@link MethodSafety#check(java.util.List)}
132 * </ul>
133 *
134 * @since 10.0.0
135 */
136@Target(METHOD)
137@Retention(RUNTIME)
138@Inherited
139public @interface Mutating {
140
141   /**
142    * Optional note describing what this operation changes.
143    *
144    * <p>
145    * Included in the startup failure message when this operation is bound to a safe method, so the error can say
146    * what is at stake rather than only which method is wrong.  Has no other effect.
147    *
148    * @return The description of what this operation changes.
149    */
150   String value() default "";
151}